@taskctrl/canvas-timeline 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CanvasTimeline.d.ts +3 -0
- package/dist/canvas/CanvasManager.d.ts +23 -0
- package/dist/canvas/DrawHelpers.d.ts +6 -0
- package/dist/canvas/GridLayer.d.ts +5 -0
- package/dist/canvas/ItemsLayer.d.ts +8 -0
- package/dist/canvas/OverlayLayer.d.ts +20 -0
- package/dist/canvas-timeline.cjs.js +2 -0
- package/dist/canvas-timeline.cjs.js.map +1 -0
- package/dist/canvas-timeline.es.js +1316 -0
- package/dist/canvas-timeline.es.js.map +1 -0
- package/dist/core/HitTest.d.ts +7 -0
- package/dist/core/IntervalTree.d.ts +7 -0
- package/dist/core/LayoutEngine.d.ts +15 -0
- package/dist/core/ViewState.d.ts +40 -0
- package/dist/dom/CustomHeader.d.ts +9 -0
- package/dist/dom/CustomMarker.d.ts +13 -0
- package/dist/dom/DateHeader.d.ts +20 -0
- package/dist/dom/Sidebar.d.ts +14 -0
- package/dist/dom/SidebarHeader.d.ts +13 -0
- package/dist/dom/TimelineHeaders.d.ts +18 -0
- package/dist/dom/TodayMarker.d.ts +15 -0
- package/dist/index.d.ts +9 -0
- package/dist/interaction/InteractionHandler.d.ts +35 -0
- package/dist/interaction/ScrollHandler.d.ts +9 -0
- package/dist/interaction/ZoomHandler.d.ts +10 -0
- package/dist/types.d.ts +149 -0
- package/package.json +7 -2
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resize the canvas buffer only when dimensions actually change.
|
|
3
|
+
* Setting canvas.width/height is destructive (clears buffer + resets state),
|
|
4
|
+
* so we avoid it unless necessary.
|
|
5
|
+
*/
|
|
6
|
+
export declare function setupCanvas(canvas: HTMLCanvasElement, width: number, height: number): CanvasRenderingContext2D;
|
|
7
|
+
export declare function clearCanvas(ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement): void;
|
|
8
|
+
export type LayerName = 'grid' | 'items' | 'overlay';
|
|
9
|
+
export interface DirtyFlags {
|
|
10
|
+
grid: boolean;
|
|
11
|
+
items: boolean;
|
|
12
|
+
overlay: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class RenderScheduler {
|
|
15
|
+
private dirty;
|
|
16
|
+
private rafId;
|
|
17
|
+
private drawCallback;
|
|
18
|
+
constructor(drawCallback: (flags: DirtyFlags) => void);
|
|
19
|
+
markDirty(layer: LayerName): void;
|
|
20
|
+
markAllDirty(): void;
|
|
21
|
+
dispose(): void;
|
|
22
|
+
private schedule;
|
|
23
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DrawHelpers, ItemBounds } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a DrawHelpers object bound to the given canvas context and optional item bounds.
|
|
4
|
+
* These helpers are passed to every itemRenderer call to simplify common canvas operations.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createDrawHelpers(ctx: CanvasRenderingContext2D, bounds?: ItemBounds): DrawHelpers;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Group, TimelineTheme, DayStyle, RowStyle } from '../types';
|
|
2
|
+
import type { ViewState } from '../core/ViewState';
|
|
3
|
+
export declare class GridLayer {
|
|
4
|
+
draw(ctx: CanvasRenderingContext2D, view: ViewState, groups: Group[], theme: TimelineTheme, dayStyle?: (date: Date) => DayStyle | null, rowStyle?: (group: Group) => RowStyle | null): void;
|
|
5
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Item, Group, TimelineTheme, CanvasItemRenderer, CanvasGroupItemRenderer, Dependency } from '../types';
|
|
2
|
+
import type { ViewState } from '../core/ViewState';
|
|
3
|
+
import type { IntervalTree } from '../core/IntervalTree';
|
|
4
|
+
import type { LayoutEngine } from '../core/LayoutEngine';
|
|
5
|
+
export declare class ItemsLayer {
|
|
6
|
+
draw(ctx: CanvasRenderingContext2D, view: ViewState, groups: Group[], _items: Item[], tree: IntervalTree<Item>, layout: LayoutEngine, itemRenderer: CanvasItemRenderer, groupRenderer: CanvasGroupItemRenderer | undefined, theme: TimelineTheme, selected: number[], hoveredItemId: number | undefined, dependencies?: Dependency[]): void;
|
|
7
|
+
private drawDependencies;
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TimelineTheme, MarkerConfig, ItemBounds, Item, CanvasItemRenderer } from '../types';
|
|
2
|
+
import type { ViewState } from '../core/ViewState';
|
|
3
|
+
import type { InteractionMode } from '../interaction/InteractionHandler';
|
|
4
|
+
export interface InteractionRenderState {
|
|
5
|
+
item: Item;
|
|
6
|
+
mode: InteractionMode;
|
|
7
|
+
bounds: ItemBounds;
|
|
8
|
+
renderer: CanvasItemRenderer;
|
|
9
|
+
targetGroupY?: number;
|
|
10
|
+
groupChanged?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface OverlayDrawOptions {
|
|
13
|
+
cursorX: number | null;
|
|
14
|
+
snapX?: number | null;
|
|
15
|
+
markers?: MarkerConfig[];
|
|
16
|
+
interaction?: InteractionRenderState | null;
|
|
17
|
+
}
|
|
18
|
+
export declare class OverlayLayer {
|
|
19
|
+
draw(ctx: CanvasRenderingContext2D, view: ViewState, theme: TimelineTheme, options: OverlayDrawOptions): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const X=require("react/jsx-runtime"),u=require("react"),er=require("react-dom"),ee=require("dayjs"),ae={primary:"#269bf7",trainColors:{},status:{red:"#EF5350",yellow:"#FBBF24",green:"#31c48d"},grid:{line:"#E5E5E5",rowAlt:"#F7F7F7",weekend:"rgba(0,0,0,0.03)"},item:{radius:3,text:"#374151",selectedRing:"#a3a3a3"},marker:{today:"#FD7171",milestone:"#3B82F6",cursor:"#269bf7"},sidebar:{bg:"#F9FAFB",border:"#E5E7EB",text:"#6c737f"},header:{bg:"#F9FAFB",border:"#E5E7EB",text:"#6c737f"}};class Ue{constructor(e){Object.defineProperty(this,"visibleTimeStart",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"visibleTimeEnd",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"canvasWidth",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"canvasHeight",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"sidebarWidth",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"lineHeight",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"groupCount",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"buffer",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"scrollTop",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"visibleDuration",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"pixelsPerMs",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.visibleTimeStart=e.visibleTimeStart,this.visibleTimeEnd=e.visibleTimeEnd,this.canvasWidth=e.canvasWidth,this.canvasHeight=e.canvasHeight,this.sidebarWidth=e.sidebarWidth,this.lineHeight=e.lineHeight,this.groupCount=e.groupCount,this.buffer=e.buffer,this.scrollTop=e.scrollTop,this.visibleDuration=this.visibleTimeEnd-this.visibleTimeStart,this.pixelsPerMs=this.canvasWidth/this.visibleDuration}update(e){e.visibleTimeStart!==void 0&&(this.visibleTimeStart=e.visibleTimeStart),e.visibleTimeEnd!==void 0&&(this.visibleTimeEnd=e.visibleTimeEnd),e.canvasWidth!==void 0&&(this.canvasWidth=e.canvasWidth),e.canvasHeight!==void 0&&(this.canvasHeight=e.canvasHeight),e.sidebarWidth!==void 0&&(this.sidebarWidth=e.sidebarWidth),e.lineHeight!==void 0&&(this.lineHeight=e.lineHeight),e.groupCount!==void 0&&(this.groupCount=e.groupCount),e.buffer!==void 0&&(this.buffer=e.buffer),e.scrollTop!==void 0&&(this.scrollTop=e.scrollTop),this.visibleDuration=this.visibleTimeEnd-this.visibleTimeStart,this.pixelsPerMs=this.canvasWidth/this.visibleDuration}timeToX(e){return(e-this.visibleTimeStart)*this.pixelsPerMs}xToTime(e){return this.visibleTimeStart+e/this.pixelsPerMs}yToGroupIndex(e){const r=Math.floor((e+this.scrollTop)/this.lineHeight);return Math.max(0,Math.min(r,this.groupCount-1))}groupIndexToY(e){return e*this.lineHeight-this.scrollTop}getBufferBounds(){const e=this.visibleDuration*1.5;return{bufferStart:this.visibleTimeStart-e,bufferEnd:this.visibleTimeEnd+e}}getVisibleGroupRange(){const e=Math.max(0,Math.floor(this.scrollTop/this.lineHeight)),r=Math.ceil(this.canvasHeight/this.lineHeight),o=Math.min(this.groupCount-1,e+r);return{firstVisible:e,lastVisible:o}}isScrollInBuffer(e){const r=this.visibleDuration*1.5*this.pixelsPerMs;return Math.abs(e)<r}getTotalHeight(){return this.groupCount*this.lineHeight}}class tr{constructor(){Object.defineProperty(this,"root",{enumerable:!0,configurable:!0,writable:!0,value:null})}buildFromItems(e,r,o){const l=e.map(c=>({item:c,start:r(c),end:o(c)}));this.root=this.buildNode(l)}buildNode(e){if(e.length===0)return null;let r=1/0,o=-1/0;for(const f of e)f.start<r&&(r=f.start),f.end>o&&(o=f.end);const l=(r+o)/2,c=[],a=[],b=[];for(const f of e)f.end<l?c.push(f):f.start>l?a.push(f):b.push(f);return{center:l,left:this.buildNode(c),right:this.buildNode(a),overlapping:b}}query(e,r){const o=[];return this.queryNode(this.root,e,r,o),o}queryNode(e,r,o,l){if(e!==null){for(const c of e.overlapping)c.start<=o&&c.end>=r&&l.push(c.item);r<=e.center&&e.left!==null&&this.queryNode(e.left,r,o,l),o>=e.center&&e.right!==null&&this.queryNode(e.right,r,o,l)}}}class rr{constructor(e,r){Object.defineProperty(this,"lineHeight",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"itemHeightRatio",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"layoutCache",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"groupMaxStack",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),this.lineHeight=e,this.itemHeightRatio=r}computeLayout(e,r){if(this.layoutCache=new Map,this.groupMaxStack=new Map,!r){const c=this.lineHeight*this.itemHeightRatio;for(const a of e)this.layoutCache.set(a.id,{stackLevel:0,itemHeight:c}),this.groupMaxStack.set(a.group,0);return this.layoutCache}const o=new Map;for(const c of e){let a=o.get(c.group);a||(a=[],o.set(c.group,a)),a.push(c)}const l=this.lineHeight*this.itemHeightRatio;for(const[c,a]of o){a.sort((v,T)=>{const y=v.start_time-T.start_time;return y!==0?y:T.end_time-T.start_time-(v.end_time-v.start_time)});const b=[];let f=0;for(const v of a){let T=-1;for(let y=0;y<b.length;y++)if(b[y]<=v.start_time){T=y;break}T===-1?(T=b.length,b.push(v.end_time)):b[T]=v.end_time,T>f&&(f=T),this.layoutCache.set(v.id,{stackLevel:T,itemHeight:l})}this.groupMaxStack.set(c,f)}return this.layoutCache}getLayout(e){return this.layoutCache.get(e)}getGroupHeight(e){return((this.groupMaxStack.get(e)??0)+1)*this.lineHeight}}function De(t,e,r,o,l,c){const a=r.xToTime(t),b=new Map;for(let y=0;y<c.length;y++)b.set(c[y].id,y);const f=o.query(a,a);let v=null,T=-1/0;for(const y of f){const H=b.get(y.group);if(H===void 0)continue;const k=l.getLayout(y.id);if(!k)continue;const M=r.timeToX(y.start_time),I=r.timeToX(y.end_time)-M;if(t<M||t>M+I)continue;const S=r.groupIndexToY(H)+k.stackLevel*r.lineHeight+(r.lineHeight-k.itemHeight)/2,O=k.itemHeight;e<S||e>S+O||S>T&&(T=S,v=y)}return v}function Ke(t,e,r){const o=e.yToGroupIndex(t);return r[o]??null}function yt(t,e,r,o=6){const l=r.timeToX(e.start_time),c=r.timeToX(e.end_time);return t-l<=o?"left":c-t<=o?"right":"body"}function Je(t,e,r){const o=window.devicePixelRatio||1,l=Math.round(e*o),c=Math.round(r*o);(t.width!==l||t.height!==c)&&(t.width=l,t.height=c,t.style.width=`${e}px`,t.style.height=`${r}px`);const a=t.getContext("2d");return a.setTransform(o,0,0,o,0,0),a}function Qe(t,e){const r=window.devicePixelRatio||1;t.clearRect(0,0,e.width/r,e.height/r)}class ir{constructor(e){Object.defineProperty(this,"dirty",{enumerable:!0,configurable:!0,writable:!0,value:{grid:!1,items:!1,overlay:!1}}),Object.defineProperty(this,"rafId",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"drawCallback",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.drawCallback=e}markDirty(e){this.dirty[e]=!0,this.schedule()}markAllDirty(){this.dirty.grid=!0,this.dirty.items=!0,this.dirty.overlay=!0,this.schedule()}dispose(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}schedule(){this.rafId===null&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null;const e={...this.dirty};this.dirty.grid=!1,this.dirty.items=!1,this.dirty.overlay=!1,this.drawCallback(e)}))}}class nr{draw(e,r,o,l,c,a){const{firstVisible:b,lastVisible:f}=r.getVisibleGroupRange();for(let S=b;S<=f;S++){const O=r.groupIndexToY(S),j=o[S];if(!j)continue;let N;const z=a==null?void 0:a(j);z!=null&&z.backgroundColor?N=z.backgroundColor:N=S%2===0?"#FFFFFF":l.grid.rowAlt,e.fillStyle=N,e.fillRect(0,O,r.canvasWidth,r.lineHeight),e.strokeStyle=(z==null?void 0:z.borderBottomColor)??l.grid.line,e.lineWidth=.5,e.beginPath(),e.moveTo(0,O+r.lineHeight),e.lineTo(r.canvasWidth,O+r.lineHeight),e.stroke()}const v=r.visibleTimeStart,T=r.visibleTimeEnd,k=864e5/(T-v)*r.canvasWidth;let M="day";k<2?M="month":k<8&&(M="week");{let S=ee(v).startOf("day");const O=ee(T).endOf("day");let j=null,N=1,z=0;const x=[],ie=V=>{j!==null&&(e.fillStyle=j,N!==1&&(e.globalAlpha=N),e.fillRect(z,0,V-z,r.canvasHeight),N!==1&&(e.globalAlpha=1),j=null,N=1)};for(;S.isBefore(O);){const V=r.timeToX(S.valueOf()),Ce=S.toDate(),Z=c==null?void 0:c(Ce);let te=null,ne=1;if(Z!=null&&Z.backgroundColor)te=Z.backgroundColor,ne=Z.opacity??1;else{const me=S.day();(me===0||me===6)&&(te=l.grid.weekend)}Z!=null&&Z.borderColor&&x.push({x:V,color:Z.borderColor}),te===j&&ne===N||(ie(V),te!==null&&(j=te,N=ne,z=V)),S=S.add(1,"day")}j!==null&&ie(r.timeToX(S.valueOf()));for(const V of x)e.strokeStyle=V.color,e.lineWidth=.5,e.beginPath(),e.moveTo(V.x,0),e.lineTo(V.x,r.canvasHeight),e.stroke()}let I=ee(v).startOf(M);const W=ee(T).add(1,M);for(e.strokeStyle=l.grid.line,e.lineWidth=.5,e.beginPath();I.isBefore(W);){const S=r.timeToX(I.valueOf());e.moveTo(S,0),e.lineTo(S,r.canvasHeight),I=I.add(1,M)}e.stroke()}}const Tt='500 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';function Ht(t,e){return{roundRect(r,o,l,c,a=3){t.beginPath(),t.roundRect(r,o,l,c,a),t.fill()},fillText(r,o,l,c){if(t.font=Tt,c!==void 0&&t.measureText(r).width>c){let a=0,b=r.length;for(;a<b;){const f=Math.ceil((a+b)/2),v=r.slice(0,f)+"...";t.measureText(v).width<=c?a=f:b=f-1}t.fillText(r.slice(0,a)+"...",o,l)}else t.fillText(r,o,l)},gradient(r,o,l,c){const a=t.createLinearGradient(r,0,r+o,0);return a.addColorStop(0,l),a.addColorStop(.5,l),a.addColorStop(.5,c),a.addColorStop(1,c),a},leftBar(r,o=3){e&&(t.save(),t.fillStyle=r,t.fillRect(e.x,e.y,o,e.height),t.restore())},icon(r,o,l,c=14){t.save();const a=c/2;if(r==="check"){t.fillStyle="#31c48d",t.beginPath(),t.arc(o+a,l+a,a,0,Math.PI*2),t.fill(),t.strokeStyle="#ffffff",t.lineWidth=c*.12,t.beginPath();const b=o+a,f=l+a;t.moveTo(b-a*.45,f),t.lineTo(b-a*.1,f+a*.42),t.lineTo(b+a*.45,f-a*.35),t.stroke()}else if(r==="danger-red"||r==="danger-yellow"){const b=r==="danger-red"?"#EF5350":"#FBBF24";t.fillStyle=b,t.beginPath(),t.moveTo(o+a,l),t.lineTo(o+c,l+c),t.lineTo(o,l+c),t.closePath(),t.fill(),t.fillStyle="#ffffff";const f=c*.12,v=o+a-f/2;t.fillRect(v,l+c*.35,f,c*.35),t.beginPath(),t.arc(o+a,l+c*.82,f*.7,0,Math.PI*2),t.fill()}t.restore()},badge(r,o,l,c){t.save(),t.font=Tt;const b=t.measureText(r).width,f=8,T=12+3*2,y=b+f*2,H=T/2;t.fillStyle=c,t.beginPath(),t.roundRect(o,l,y,T,H),t.fill(),t.fillStyle="#ffffff",t.textAlign="center",t.textBaseline="middle",t.fillText(r,o+y/2,l+T/2),t.restore()}}}class sr{draw(e,r,o,l,c,a,b,f,v,T,y,H){const k=(r.visibleTimeEnd-r.visibleTimeStart)*.1,M=r.visibleTimeStart-k,I=r.visibleTimeEnd+k,W=c.query(M,I),S=new Map;for(let x=0;x<o.length;x++)S.set(o[x].id,x);const O=new Set(T),j=new Map,N=-r.lineHeight,z=r.canvasHeight+r.lineHeight;for(const x of W){const ie=S.get(x.group);if(ie===void 0)continue;const V=a.getLayout(x.id);if(!V)continue;const Z=r.groupIndexToY(ie)+V.stackLevel*r.lineHeight+(r.lineHeight-V.itemHeight)/2,te=V.itemHeight;if(Z+te<N||Z>z)continue;const ne=r.timeToX(x.start_time),me=r.timeToX(x.end_time)-ne,be={x:ne,y:Z,width:me,height:te};j.set(x.id,be);const Pe={selected:O.has(x.id),hovered:y===x.id,dragging:!1,filtered:x.filtered!==!1};e.save();const Ie=Ht(e,be);(f&&(x.type==="control_area_group"||x.type==="construction_train")?f:b)(e,x,be,Pe,Ie),e.restore()}H&&H.length>0&&this.drawDependencies(e,H,j,y,v)}drawDependencies(e,r,o,l,c){for(const a of r){const b=o.get(a.fromItemId),f=o.get(a.toItemId);if(!b||!f)continue;const v=l===a.fromItemId||l===a.toItemId;e.strokeStyle=v?c.primary:a.color??"#94A3B8",e.lineWidth=v?2:1.5,e.setLineDash([]);const T=b.x+b.width,y=b.y+b.height/2,H=f.x,k=f.y+f.height/2,M=Math.abs(H-T),I=Math.max(M*.4,30);e.beginPath(),e.moveTo(T,y),e.bezierCurveTo(T+I,y,H-I,k,H,k),e.stroke();const W=6;e.fillStyle=e.strokeStyle,e.beginPath(),e.moveTo(H,k),e.lineTo(H-W,k-W/2),e.lineTo(H-W,k+W/2),e.closePath(),e.fill()}}}class or{draw(e,r,o,l){const{cursorX:c,snapX:a,markers:b,interaction:f}=l;if(b)for(const v of b){const T=r.timeToX(v.date);if(e.fillStyle=v.color,e.fillRect(T-v.width/2,0,v.width,r.canvasHeight),v.label){e.save(),e.font='500 10px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';const y=e.measureText(v.label).width,H=8,k=200,M=Math.min(y+H*2,k),I=20,W=T-M/2,S=4;e.fillStyle=v.color,e.beginPath(),e.roundRect(W,S,M,I,3),e.fill(),e.fillStyle="#FFFFFF",e.textBaseline="middle";const O=k-H*2,j=y>O?v.label.slice(0,Math.floor(v.label.length*O/y))+"…":v.label;e.fillText(j,W+H,S+I/2),e.restore()}}if(c!=null&&(e.strokeStyle=o.marker.cursor,e.lineWidth=1,e.beginPath(),e.moveTo(c,0),e.lineTo(c,r.canvasHeight),e.stroke()),a!=null&&(e.strokeStyle=o.primary,e.lineWidth=1,e.setLineDash([4,4]),e.beginPath(),e.moveTo(a,0),e.lineTo(a,r.canvasHeight),e.stroke(),e.setLineDash([])),f){f.groupChanged&&f.targetGroupY!==void 0&&(e.fillStyle="rgba(59, 130, 246, 0.08)",e.fillRect(0,f.targetGroupY,r.canvasWidth,r.lineHeight)),e.save(),e.globalAlpha=.5;const v=Ht(e,f.bounds);f.renderer(e,f.item,f.bounds,{selected:!1,hovered:!1,dragging:!0,filtered:!0},v),e.restore()}}}const kt=120;function lr(t){let e=t.deltaY||t.deltaX;return t.deltaMode===1?e*=15:t.deltaMode===2&&(e*=800),Math.max(-kt,Math.min(kt,e))}class ar{constructor(e,r,o,l,c){Object.defineProperty(this,"onZoom",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"visibleTimeStart",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"visibleTimeEnd",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"minZoom",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"maxZoom",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.onZoom=e,this.visibleTimeStart=r,this.visibleTimeEnd=o,this.minZoom=l,this.maxZoom=c}updateBounds(e,r){this.visibleTimeStart=e,this.visibleTimeEnd=r}handleWheelZoom(e,r){const o=lr(e),l=e.ctrlKey?10:e.metaKey?3:1,c=o>0?1+l*o/500:1/(1+l*-o/500),a=this.visibleTimeEnd-this.visibleTimeStart;let b=Math.round(a*c);b=Math.max(this.minZoom,Math.min(this.maxZoom,b));const f=Math.round(this.visibleTimeStart+(a-b)*r),v=f+b;this.onZoom(f,v)}}const ur=4;class cr{constructor(e){Object.defineProperty(this,"state",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"dragSnap",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"activated",{enumerable:!0,configurable:!0,writable:!0,value:!1}),this.dragSnap=e}startInteraction(e,r,o,l){this.state={item:e,mode:r,startX:o,startY:l,currentX:o,currentY:l,deltaX:0,originalGroup:e.group,currentGroup:e.group},this.activated=!1}update(e,r){this.state&&(this.state.currentX=e,this.state.currentY=r,this.state.deltaX=e-this.state.startX,!this.activated&&Math.abs(this.state.deltaX)>=ur&&(this.activated=!0))}setCurrentGroup(e){this.state&&(this.state.currentGroup=e)}endMove(e){if(!this.state)return null;const r=this.state.deltaX/e,o=this.state.item.start_time+r,l=Math.round(o/this.dragSnap)*this.dragSnap,c=this.state.currentGroup;return this.state=null,this.activated=!1,{newStartTime:l,newGroupId:c}}endResize(e){if(!this.state)return null;const r=this.state.deltaX/e,o=this.state.mode==="resize-left"?"left":"right",c=(o==="left"?this.state.item.start_time:this.state.item.end_time)+r,a=Math.round(c/this.dragSnap)*this.dragSnap;return this.state=null,this.activated=!1,{newTime:a,edge:o}}cancel(){this.state=null,this.activated=!1}getState(){return this.state}getMode(){var e;return((e=this.state)==null?void 0:e.mode)??null}isActive(){return this.state!==null&&this.activated}isPending(){return this.state!==null}}var Rt=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Dt(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Pt={exports:{}};(function(t,e){(function(r,o){t.exports=o()})(Rt,function(){var r="day";return function(o,l,c){var a=function(v){return v.add(4-v.isoWeekday(),r)},b=l.prototype;b.isoWeekYear=function(){return a(this).year()},b.isoWeek=function(v){if(!this.$utils().u(v))return this.add(7*(v-this.isoWeek()),r);var T,y,H,k,M=a(this),I=(T=this.isoWeekYear(),y=this.$u,H=(y?c.utc:c)().year(T).startOf("year"),k=4-H.isoWeekday(),H.isoWeekday()>4&&(k+=7),H.add(k,r));return M.diff(I,"week")+1},b.isoWeekday=function(v){return this.$utils().u(v)?this.day()||7:this.day(this.day()%7?v:v-7)};var f=b.startOf;b.startOf=function(v,T){var y=this.$utils(),H=!!y.u(T)||T;return y.p(v)==="isoweek"?H?this.date(this.date()-(this.isoWeekday()-1)).startOf("day"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf("day"):f.bind(this)(v,T)}}})})(Pt);var dr=Pt.exports;const fr=Dt(dr),wt=5;function Ct({groups:t,width:e,lineHeight:r,scrollTop:o,canvasHeight:l,theme:c,groupRenderer:a,onScroll:b}){var W;const f=u.useRef(null),v=u.useRef(!1),T=t.length*r,y=l,H=Math.max(0,Math.floor(o/r)-wt),k=Math.min(t.length-1,Math.ceil((o+l)/r)+wt),M=u.useCallback(S=>{v.current||b(S.currentTarget.scrollTop)},[b]);u.useEffect(()=>{f.current&&(v.current=!0,f.current.scrollTop=o,requestAnimationFrame(()=>{v.current=!1}))},[o]);const I=[];for(let S=H;S<=k;S++){const O=t[S];O&&I.push(X.jsx("div",{style:{position:"absolute",top:S*r,height:r,width:"100%",overflow:"hidden",display:"flex",alignItems:"stretch",borderBottom:`1px solid ${((W=c.grid)==null?void 0:W.line)??"#E5E5E5"}`,boxSizing:"border-box"},children:a(O)},O.id))}return X.jsx("div",{ref:f,onScroll:M,style:{width:e,height:y,overflowY:T>l?"auto":"hidden",overflowX:"hidden",position:"relative",borderRight:`1px solid ${c.sidebar.border}`,backgroundColor:c.sidebar.bg},children:X.jsx("div",{style:{height:T,position:"relative"},children:I})})}function It(t){return null}It.displayName="TodayMarker";function Et(t){return{date:Math.floor(Date.now()/6e4)*6e4,color:t.color??"#FD7171",width:t.width??6,label:t.label}}function hr(t){return t.interval??1e4}function Ot(t){return null}Ot.displayName="CustomMarker";function St(t){return{date:t.date,color:t.color??"#3B82F6",width:t.width??4,label:t.label}}ee.extend(fr);function mr(t){return t?{...ae,...t,status:{...ae.status,...t.status},grid:{...ae.grid,...t.grid},item:{...ae.item,...t.item},marker:{...ae.marker,...t.marker},sidebar:{...ae.sidebar,...t.sidebar},header:{...ae.header,...t.header}}:ae}const Mt=32,gr=u.memo(u.forwardRef(function(e,r){const{groups:o,items:l,defaultTimeStart:c,defaultTimeEnd:a,sidebarWidth:b,lineHeight:f,itemHeightRatio:v,stackItems:T,canMove:y,canChangeGroup:H,canResize:k,dragSnap:M,minZoom:I,maxZoom:W,theme:S,dayStyle:O,rowStyle:j,showCursorLine:N,itemRenderer:z,groupRenderer:x,sidebarGroupRenderer:ie,dependencies:V,onItemClick:Ce,onItemDoubleClick:Z,onItemContextMenu:te,onItemMove:ne,onItemResize:me,moveResizeValidator:be,onItemHover:Pe,onCanvasDoubleClick:Ie,onCanvasContextMenu:je,onTimeChange:et,onZoom:tt,selected:rt=[],rightSidebarWidth:Xe,rightSidebarGroupRenderer:it,onReady:Oe,children:ue}=e,ge=u.useMemo(()=>mr(S),[S]),nt=u.useCallback((s,i)=>{for(let d=0;d<i.length;d++)if(i[d].id===s)return d;return 0},[]),Xt=rt.join(","),Le=u.useMemo(()=>rt,[Xt]),st=u.useRef(null),ot=u.useRef(null),lt=u.useRef(null),Ee=u.useRef(null),at=u.useRef(null),Lt=u.useRef(null),[ut,_t]=u.useState({width:800,height:600});u.useEffect(()=>{const s=at.current;if(!s)return;const i=new ResizeObserver(d=>{const m=d[0];m&&_t({width:m.contentRect.width,height:m.contentRect.height})});return i.observe(s),()=>i.disconnect()},[]);const ce=Math.max(0,ut.width-b-(Xe??0)),de=o.length*f||ut.height,D=u.useRef(new Ue({visibleTimeStart:e.visibleTimeStart??c,visibleTimeEnd:e.visibleTimeEnd??a,canvasWidth:ce,canvasHeight:de,sidebarWidth:b,lineHeight:f,groupCount:o.length,buffer:e.buffer??3,scrollTop:0})),_e=u.useRef(null),Se=u.useRef(void 0),[ct,At]=u.useState(e.visibleTimeStart??c),[dt,Yt]=u.useState(e.visibleTimeEnd??a),[ft,Fe]=u.useState(0),Me=u.useRef(null),pe=u.useCallback(()=>{const s=D.current;At(s.visibleTimeStart),Yt(s.visibleTimeEnd),Fe(s.scrollTop),Me.current=null},[]),Ae=u.useCallback(()=>{Me.current===null&&(Me.current=setTimeout(pe,Mt))},[pe]);u.useEffect(()=>()=>{Me.current!==null&&clearTimeout(Me.current)},[]);const Ye=u.useMemo(()=>{const s=new tr;return s.buildFromItems(l,i=>i.start_time,i=>i.end_time),s},[l]),Ne=u.useMemo(()=>{const s=new rr(f,v);return s.computeLayout(l,T),s},[l,f,v,T]),ye=u.useMemo(()=>new nr,[]),Te=u.useMemo(()=>new sr,[]),ke=u.useMemo(()=>new or,[]),G=u.useMemo(()=>new cr(M),[M]),Be=u.useMemo(()=>{const s=[];return u.Children.forEach(ue,i=>{var m;if(!u.isValidElement(i))return;const d=(m=i.type)==null?void 0:m.displayName;d==="TodayMarker"?s.push(Et(i.props)):d==="CustomMarker"&&s.push(St(i.props))}),s},[ue]),We=u.useMemo(()=>Be.map(s=>`${s.date}|${s.color}|${s.width}|${s.label??""}`).join(";"),[Be]),He=u.useRef(Be);He.current=Be;const Ge=u.useMemo(()=>{let s=0;return u.Children.forEach(ue,i=>{var m;if(!u.isValidElement(i))return;((m=i.type)==null?void 0:m.displayName)==="TodayMarker"&&(s=hr(i.props))}),s},[ue]),F=u.useRef({groups:o,items:l,intervalTree:Ye,layoutEngine:Ne,itemRenderer:z,groupRenderer:x,theme:ge,selected:Le,dependencies:V,dayStyle:O,rowStyle:j,showCursorLine:N,canvasWidth:ce,canvasHeight:de,lineHeight:f,itemHeightRatio:v,onTimeChange:et,onZoom:tt,onItemHover:Pe,onItemClick:Ce,onItemDoubleClick:Z,onItemContextMenu:te,onItemMove:ne,onItemResize:me,onCanvasDoubleClick:Ie,onCanvasContextMenu:je,canMove:y,canResize:k,canChangeGroup:H,dragSnap:M,sidebarWidth:b,moveResizeValidator:be});F.current={groups:o,items:l,intervalTree:Ye,layoutEngine:Ne,itemRenderer:z,groupRenderer:x,theme:ge,selected:Le,dependencies:V,dayStyle:O,rowStyle:j,showCursorLine:N,canvasWidth:ce,canvasHeight:de,lineHeight:f,itemHeightRatio:v,onTimeChange:et,onZoom:tt,onItemHover:Pe,onItemClick:Ce,onItemDoubleClick:Z,onItemContextMenu:te,onItemMove:ne,onItemResize:me,onCanvasDoubleClick:Ie,onCanvasContextMenu:je,canMove:y,canResize:k,canChangeGroup:H,dragSnap:M,sidebarWidth:b,moveResizeValidator:be};const Nt=u.useCallback(()=>{const s=st.current;if(!s)return;const i=F.current,d=Je(s,i.canvasWidth,i.canvasHeight);Qe(d,s),ye.draw(d,D.current,i.groups,i.theme,i.dayStyle,i.rowStyle)},[ye]),Gt=u.useCallback(()=>{const s=ot.current;if(!s)return;const i=F.current,d=Je(s,i.canvasWidth,i.canvasHeight);Qe(d,s),Te.draw(d,D.current,i.groups,i.items,i.intervalTree,i.layoutEngine,i.itemRenderer,i.groupRenderer,i.theme,i.selected,Se.current,i.dependencies)},[Te]),ht=u.useCallback((s,i)=>{const d=D.current,m=F.current,n=m.canvasWidth/(d.visibleTimeEnd-d.visibleTimeStart),h=i/n,p=s.start_time+h,w=Math.round(p/m.dragSnap)*m.dragSnap;return d.timeToX(w)},[]),zt=u.useCallback(()=>{const s=lt.current;if(!s)return;const i=F.current,d=Je(s,i.canvasWidth,i.canvasHeight);Qe(d,s);const m=D.current,n=G.getState();let h=null;if(n){const p=m.timeToX(n.item.start_time),w=m.timeToX(n.item.end_time)-p;let R,P;n.mode==="resize-left"?(R=p+n.deltaX,P=w-n.deltaX):n.mode==="resize-right"?(R=p,P=w+n.deltaX):(R=p+n.deltaX,P=w);const _=nt(n.currentGroup,i.groups),$=m.groupIndexToY(_),A=n.currentGroup!==n.originalGroup;h={item:n.item,mode:n.mode,bounds:{x:R,y:$+(i.lineHeight-i.lineHeight*i.itemHeightRatio)/2,width:P,height:i.lineHeight*i.itemHeightRatio},renderer:i.itemRenderer,targetGroupY:$,groupChanged:A}}ke.draw(d,m,i.theme,{cursorX:i.showCursorLine?_e.current:null,snapX:n?ht(n.item,n.deltaX):null,markers:He.current,interaction:h})},[ke,G,ht,nt]),ze=u.useRef(null);ze.current||(ze.current=new ir(s=>{s.grid&&Nt(),s.items&&Gt(),s.overlay&&zt()}));const E=ze.current;u.useEffect(()=>()=>E.dispose(),[E]),u.useEffect(()=>{if(!Ge)return;const s=setInterval(()=>{const i=[];u.Children.forEach(ue,d=>{var n;if(!u.isValidElement(d))return;const m=(n=d.type)==null?void 0:n.displayName;m==="TodayMarker"?i.push(Et(d.props)):m==="CustomMarker"&&i.push(St(d.props))}),He.current=i,E.markDirty("overlay")},Ge);return()=>clearInterval(s)},[Ge,ue,E]),u.useEffect(()=>{D.current.update({canvasWidth:ce,canvasHeight:de,sidebarWidth:b,lineHeight:f,groupCount:o.length}),E.markAllDirty()},[ce,de,b,f,o.length,E]),u.useEffect(()=>{E.markDirty("grid"),E.markDirty("items")},[l,o,Le,ge,O,j,Ye,Ne,E]);const mt=u.useRef(We);u.useEffect(()=>{We!==mt.current&&(mt.current=We,E.markDirty("overlay"))},[We,E]);const gt=u.useRef(e.visibleTimeStart),vt=u.useRef(e.visibleTimeEnd);e.visibleTimeStart!==void 0&&e.visibleTimeStart!==gt.current&&(gt.current=e.visibleTimeStart,D.current.update({visibleTimeStart:e.visibleTimeStart}),E.markAllDirty()),e.visibleTimeEnd!==void 0&&e.visibleTimeEnd!==vt.current&&(vt.current=e.visibleTimeEnd,D.current.update({visibleTimeEnd:e.visibleTimeEnd}),E.markAllDirty());const Re=u.useRef(null),$e=u.useCallback(s=>{Re.current===null&&(Re.current=setTimeout(()=>{var m,n;Re.current=null;const i=D.current,d=F.current;s==="zoom"?(m=d.onZoom)==null||m.call(d,i.visibleTimeStart,i.visibleTimeEnd):(n=d.onTimeChange)==null||n.call(d,i.visibleTimeStart,i.visibleTimeEnd)},Mt))},[]);u.useEffect(()=>()=>{Re.current!==null&&clearTimeout(Re.current)},[]);const xe=u.useRef(null),Ve=u.useMemo(()=>new ar((s,i)=>{var d;D.current.update({visibleTimeStart:s,visibleTimeEnd:i}),(d=xe.current)==null||d.updateBounds(s,i),E.markAllDirty(),Ae(),$e("zoom")},c,a,I,W),[]);xe.current=Ve;const bt=u.useCallback(s=>{const i=D.current,d=i.groupCount*i.lineHeight,m=Math.max(0,d-i.canvasHeight),n=Math.max(0,Math.min(m,i.scrollTop+s));n!==i.scrollTop&&(i.update({scrollTop:n}),E.markDirty("grid"),E.markDirty("items"),E.markDirty("overlay"),Fe(n))},[E]),Ze=u.useCallback(s=>{var p,w,R;const i=D.current,d=i.canvasWidth/(i.visibleTimeEnd-i.visibleTimeStart),m=s/d,n=i.visibleTimeStart+m,h=i.visibleTimeEnd+m;i.update({visibleTimeStart:n,visibleTimeEnd:h}),(p=xe.current)==null||p.updateBounds(n,h),E.markAllDirty(),er.flushSync(()=>pe()),(R=(w=F.current).onTimeChange)==null||R.call(w,n,h)},[E,pe]);u.useEffect(()=>{const s=Ee.current;if(!s)return;const i=d=>{if(d.ctrlKey||d.metaKey||d.altKey){d.preventDefault();const m=s.getBoundingClientRect(),n=(d.clientX-m.left)/m.width;Ve.handleWheelZoom(d,n)}else if(d.shiftKey)d.preventDefault(),Ze(d.deltaY);else{const m=d.deltaX;m!==0&&Math.abs(m)>Math.abs(d.deltaY)?(d.preventDefault(),Ze(m)):d.deltaY!==0&&bt(d.deltaY)}};return s.addEventListener("wheel",i,{passive:!1}),()=>s.removeEventListener("wheel",i)},[Ve,bt,Ze]);const fe=u.useRef({lastDistance:null,lastCenter:null});u.useEffect(()=>{const s=Ee.current;if(!s)return;const i=(p,w)=>Math.abs(p.clientX-w.clientX),d=(p,w,R)=>(p.clientX+w.clientX)/2-R.left,m=p=>{p.touches.length===2&&(p.preventDefault(),fe.current.lastDistance=i(p.touches[0],p.touches[1]),fe.current.lastCenter=null)},n=p=>{var w;if(p.touches.length===2&&fe.current.lastDistance!==null){p.preventDefault();const R=i(p.touches[0],p.touches[1]),P=s.getBoundingClientRect(),$=d(p.touches[0],p.touches[1],P)/P.width;if(R!==0&&fe.current.lastDistance!==0){const A=fe.current.lastDistance/R,J=D.current,q=J.visibleTimeEnd-J.visibleTimeStart;let C=q*A;C=Math.max(I,Math.min(W,C));const g=J.visibleTimeStart+q*$,Q=g-C*$,L=g+C*(1-$);J.update({visibleTimeStart:Q,visibleTimeEnd:L}),(w=xe.current)==null||w.updateBounds(Q,L),E.markAllDirty(),Ae(),$e("zoom")}fe.current.lastDistance=R}},h=()=>{fe.current.lastDistance=null,fe.current.lastCenter=null};return s.addEventListener("touchstart",m,{passive:!1}),s.addEventListener("touchmove",n,{passive:!1}),s.addEventListener("touchend",h),()=>{s.removeEventListener("touchstart",m),s.removeEventListener("touchmove",n),s.removeEventListener("touchend",h)}},[E,Ae,$e]);const $t=u.useCallback(s=>{var R;const i=s.currentTarget,d=i.getBoundingClientRect(),m=s.clientX-d.left,n=s.clientY-d.top;if(_e.current=m,G.isPending()){if(G.update(m,n),G.isActive()){const P=G.getState();if(P&&P.mode==="move"&&F.current.canChangeGroup){const _=Ke(n,D.current,F.current.groups);_&&G.setCurrentGroup(_.id)}E.markDirty("overlay")}return}F.current.showCursorLine&&E.markDirty("overlay");const h=F.current,p=De(m,n,D.current,h.intervalTree,h.layoutEngine,h.groups),w=p==null?void 0:p.id;if(w!==Se.current&&(Se.current=w,E.markDirty("items"),(R=h.onItemHover)==null||R.call(h,w??null,s.nativeEvent)),p){const P=yt(m,p,D.current),_=h.canResize;P==="left"&&(_==="left"||_==="both")||P==="right"&&(_==="right"||_==="both")?i.style.cursor="col-resize":h.canMove?i.style.cursor="grab":i.style.cursor="default"}else i.style.cursor="default"},[G,E]),Vt=u.useCallback(s=>{const i=F.current,d=s.currentTarget.getBoundingClientRect(),m=s.clientX-d.left,n=s.clientY-d.top,h=De(m,n,D.current,i.intervalTree,i.layoutEngine,i.groups);if(!h)return;const p=yt(m,h,D.current),w=i.canResize;p==="left"&&(w==="left"||w==="both")?G.startInteraction(h,"resize-left",m,n):p==="right"&&(w==="right"||w==="both")?G.startInteraction(h,"resize-right",m,n):i.canMove&&G.startInteraction(h,"move",m,n)},[G]),Zt=u.useCallback(s=>{var p,w,R,P,_,$;const i=s.currentTarget;if(G.isActive()){const A=G.getState(),J=D.current,q=J.canvasWidth/(J.visibleTimeEnd-J.visibleTimeStart);if(A){const C=F.current.moveResizeValidator;if(A.mode==="move"){const g=G.endMove(q);if(g){const Q=C?C("move",A.item.id,g.newStartTime):g.newStartTime;(w=(p=F.current).onItemMove)==null||w.call(p,A.item.id,Q,g.newGroupId)}}else{const g=G.endResize(q);if(g){const Q=C?C("resize",A.item.id,g.newTime,g.edge):g.newTime;(P=(R=F.current).onItemResize)==null||P.call(R,A.item.id,Q,g.edge)}}}i.style.cursor="default",E.markDirty("overlay");return}G.isPending()&&G.cancel();const d=i.getBoundingClientRect(),m=s.clientX-d.left,n=s.clientY-d.top,h=De(m,n,D.current,F.current.intervalTree,F.current.layoutEngine,F.current.groups);h&&(($=(_=F.current).onItemClick)==null||$.call(_,h.id,s.nativeEvent))},[G,E]),qt=u.useCallback(s=>{var p,w;const i=s.currentTarget.getBoundingClientRect(),d=s.clientX-i.left,m=s.clientY-i.top,n=F.current,h=De(d,m,D.current,n.intervalTree,n.layoutEngine,n.groups);if(h)(p=n.onItemDoubleClick)==null||p.call(n,h.id,s.nativeEvent);else{const R=Ke(m,D.current,n.groups),P=D.current.xToTime(d);R&&((w=n.onCanvasDoubleClick)==null||w.call(n,R.id,P))}},[]),Ut=u.useCallback(s=>{var p,w;s.preventDefault();const i=s.currentTarget.getBoundingClientRect(),d=s.clientX-i.left,m=s.clientY-i.top,n=F.current,h=De(d,m,D.current,n.intervalTree,n.layoutEngine,n.groups);if(h)(p=n.onItemContextMenu)==null||p.call(n,h.id,s.nativeEvent);else{const R=Ke(m,D.current,n.groups),P=D.current.xToTime(d);R&&((w=n.onCanvasContextMenu)==null||w.call(n,R.id,P,s.nativeEvent))}},[]),Kt=u.useCallback(()=>{var s,i;_e.current=null,Ee.current&&(Ee.current.style.cursor="default"),Se.current!==void 0&&(Se.current=void 0,E.markDirty("items"),(i=(s=F.current).onItemHover)==null||i.call(s,null,new PointerEvent("pointerleave"))),F.current.showCursorLine&&E.markDirty("overlay")},[E]),Jt=u.useMemo(()=>{const s=[];return u.Children.forEach(ue,i=>{var m;if(!u.isValidElement(i))return;if(((m=i.type)==null?void 0:m.displayName)==="TimelineHeaders"){const n=i.props;s.push(u.cloneElement(i,{visibleTimeStart:n.visibleTimeStart??ct,visibleTimeEnd:n.visibleTimeEnd??dt,canvasWidth:n.canvasWidth??ce,sidebarWidth:n.sidebarWidth??b,theme:n.theme??ge,onZoomToInterval:n.onZoomToInterval??((h,p)=>{var w,R,P,_;D.current.update({visibleTimeStart:h,visibleTimeEnd:p}),E.markAllDirty(),pe(),(R=(w=F.current).onTimeChange)==null||R.call(w,h,p),(_=(P=F.current).onZoom)==null||_.call(P,h,p)})}))}}),s},[ue,ct,dt,ce,b,ge,E,pe]),pt=u.useRef(!1);u.useEffect(()=>{pt.current||(pt.current=!0,E.markAllDirty())},[E]),u.useImperativeHandle(r,()=>({captureToCanvas({timeStart:s,timeEnd:i,scale:d,sidebarWidth:m}){const n=F.current,h=28,p=h*3,w=n.groups.length*n.lineHeight,R=D.current,P=n.canvasWidth/(R.visibleTimeEnd-R.visibleTimeStart),_=i-s,$=Math.max(n.canvasWidth,Math.round(_*P)),A=(m+$)*d,J=(p+w)*d,q=document.createElement("canvas");q.width=A,q.height=J;const C=q.getContext("2d");C.scale(d,d);for(let L=0;L<n.groups.length;L++){const se=n.groups[L],oe=p+L*n.lineHeight;if(n.rowStyle){const Y=n.rowStyle(se);Y!=null&&Y.backgroundColor&&(C.fillStyle=Y.backgroundColor,C.fillRect(0,oe,m,n.lineHeight))}const B=se.type;let U="400",K=8;B==="project"?U="700":B==="CAG"?U="600":B==="CA"&&(U="400",K=24),C.fillStyle="#111",C.font=`${U} 12px sans-serif`,C.textBaseline="middle",C.fillText(se.title,K,oe+n.lineHeight/2,m-K-4)}const g=(L,se,oe)=>{var K,Y;C.fillStyle=((K=n.theme.header)==null?void 0:K.bg)??"#f5f5f5",C.fillRect(m,L,$,h),C.strokeStyle=((Y=n.theme.grid)==null?void 0:Y.line)??"#e0e0e0",C.lineWidth=1,C.strokeRect(m,L,$,h);let B=ee(s).startOf(oe);B.valueOf()<s&&(B=B.add(1,oe));const U=$/(i-s);for(;B.valueOf()<i;){const he=B.add(1,oe),re=m+(B.valueOf()-s)*U,le=m+(Math.min(he.valueOf(),i)-s)*U-re;C.beginPath(),C.moveTo(re,L),C.lineTo(re,L+h),C.stroke(),C.fillStyle="#333",C.font="600 11px sans-serif",C.textBaseline="middle",C.textAlign="center",C.fillText(se(B),re+le/2,L+h/2,le-4),B=he}C.textAlign="start"};g(0,L=>L.format("YYYY"),"year"),g(h,L=>L.format("MM"),"month"),g(h*2,L=>String(L.isoWeek()),"week");const Q=new Ue({visibleTimeStart:s,visibleTimeEnd:i,canvasWidth:$,canvasHeight:w,sidebarWidth:0,lineHeight:n.lineHeight,groupCount:n.groups.length,buffer:1,scrollTop:0});return C.save(),C.translate(m,p),C.beginPath(),C.rect(0,0,$,w),C.clip(),ye.draw(C,Q,n.groups,n.theme,n.dayStyle,n.rowStyle),Te.draw(C,Q,n.groups,n.items,n.intervalTree,n.layoutEngine,n.itemRenderer,n.groupRenderer,n.theme,n.selected,void 0,n.dependencies),ke.draw(C,Q,n.theme,{cursorX:null,snapX:null,markers:He.current,interaction:null}),C.restore(),q}}),[ye,Te,ke]),u.useEffect(()=>{const s={captureToCanvas({timeStart:i,timeEnd:d,scale:m,sidebarWidth:n}){var oe;const h=F.current,p=28,w=p*3,R=h.groups.length*h.lineHeight,P=D.current,_=h.canvasWidth/(P.visibleTimeEnd-P.visibleTimeStart),$=d-i,A=Math.max(h.canvasWidth,Math.round($*_)),J=n+A,q=w+R,C=document.createElement("canvas");C.width=J*m,C.height=q*m;const g=C.getContext("2d");g.scale(m,m),g.fillStyle="#FFFFFF",g.fillRect(0,0,J,q),g.save(),g.beginPath(),g.rect(0,0,n,q),g.clip(),g.fillStyle="#F9FAFB",g.fillRect(0,0,n,w),g.strokeStyle="#E5E7EB",g.lineWidth=1,g.strokeRect(0,0,n,w);for(let B=0;B<h.groups.length;B++){const U=h.groups[B],K=w+B*h.lineHeight,Y=(oe=h.rowStyle)==null?void 0:oe.call(h,U);g.fillStyle=(Y==null?void 0:Y.backgroundColor)??(B%2===0?"#FFFFFF":"#F7F7F7"),g.fillRect(0,K,n,h.lineHeight),g.strokeStyle="#E5E5E5",g.lineWidth=.5,g.beginPath(),g.moveTo(0,K+h.lineHeight),g.lineTo(n,K+h.lineHeight),g.stroke();const he=U.type??"";let re=8,ve="400",le=11;he==="project"?(ve="700",le=12):he==="control_area_group"?ve="600":he==="control_area"&&(re=24),g.fillStyle="#374151",g.font=`${ve} ${le}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`,g.textBaseline="middle";const we=typeof U.title=="string"?U.title:String(U.title);g.fillText(we,re,K+h.lineHeight/2,n-re-8)}g.strokeStyle="#E5E7EB",g.lineWidth=1,g.beginPath(),g.moveTo(n,0),g.lineTo(n,q),g.stroke(),g.restore(),g.save(),g.beginPath(),g.rect(n,0,A,w),g.clip();const Q=d-i,L=[{unit:"year",row:0},{unit:"month",row:1},{unit:"week",row:2}];for(const{unit:B,row:U}of L){const K=U*p;g.fillStyle="#F9FAFB",g.fillRect(n,K,A,p);let Y=ee(i).startOf(B);const he=ee(d).add(1,B);for(;Y.isBefore(he);){const re=Y.add(1,B),ve=n+(Y.valueOf()-i)/Q*A,le=(re.valueOf()-Y.valueOf())/Q*A;g.strokeStyle="#E5E7EB",g.lineWidth=.5,g.strokeRect(ve,K,le,p);let we;B==="year"?we=Y.format("YYYY"):B==="month"?we=Y.format("MM"):we=`${Y.week()}`,g.fillStyle="#6c737f",g.font=B==="year"?'600 11px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif':'400 11px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',g.textBaseline="middle",g.textAlign="center",le>20&&g.fillText(we,ve+le/2,K+p/2),Y=re}}g.textAlign="start",g.restore(),g.save(),g.beginPath(),g.rect(n,w,A,R),g.clip(),g.translate(n,w);const se=new Ue({visibleTimeStart:i,visibleTimeEnd:d,canvasWidth:A,canvasHeight:R,sidebarWidth:0,lineHeight:h.lineHeight,groupCount:h.groups.length,buffer:1,scrollTop:0});return ye.draw(g,se,h.groups,h.theme,h.dayStyle,h.rowStyle),Te.draw(g,se,h.groups,h.items,h.intervalTree,h.layoutEngine,h.itemRenderer,h.groupRenderer,h.theme,h.selected,void 0,h.dependencies),ke.draw(g,se,h.theme,{cursorX:null,markers:He.current}),g.restore(),C}};Oe==null||Oe(s)},[Oe,ye,Te,ke]);const Qt={position:"relative",width:ce,height:de,overflow:"hidden",cursor:"default"},qe={position:"absolute",top:0,left:0};return X.jsxs("div",{ref:at,style:{display:"flex",flexDirection:"column",width:"100%"},children:[Jt,X.jsxs("div",{ref:Lt,style:{display:"flex",overflow:"hidden"},children:[X.jsx(Ct,{groups:o,width:b,lineHeight:f,scrollTop:ft,canvasHeight:de,theme:ge,groupRenderer:ie,onScroll:s=>{D.current.update({scrollTop:s}),E.markDirty("grid"),E.markDirty("items"),E.markDirty("overlay"),Fe(s)}}),X.jsxs("div",{ref:Ee,style:Qt,onPointerMove:$t,onPointerDown:Vt,onPointerUp:Zt,onDoubleClick:qt,onContextMenu:Ut,onPointerLeave:Kt,children:[X.jsx("canvas",{ref:st,style:{...qe,zIndex:0}}),X.jsx("canvas",{ref:ot,style:{...qe,zIndex:1}}),X.jsx("canvas",{ref:lt,style:{...qe,zIndex:2}})]}),Xe&&it?X.jsx(Ct,{groups:o,width:Xe,lineHeight:f,scrollTop:ft,canvasHeight:de,theme:ge,groupRenderer:it,onScroll:s=>{D.current.update({scrollTop:s}),E.markDirty("grid"),E.markDirty("items"),E.markDirty("overlay"),Fe(s)}}):null]})]})}));function Ft({children:t,theme:e,className:r,classNames:o,style:l,visibleTimeStart:c,visibleTimeEnd:a,canvasWidth:b,sidebarWidth:f=0,onZoomToInterval:v}){const T=u.Children.map(t,y=>{var k;if(!u.isValidElement(y))return y;if(((k=y.type)==null?void 0:k.displayName)==="DateHeader"){const M=y.props,I=u.cloneElement(y,{visibleTimeStart:M.visibleTimeStart??c,visibleTimeEnd:M.visibleTimeEnd??a,canvasWidth:M.canvasWidth??b,theme:M.theme??e,onZoomToInterval:M.onIntervalClick??M.onZoomToInterval??v});return X.jsxs("div",{style:{display:"flex"},children:[X.jsx("div",{style:{width:f,flexShrink:0}}),X.jsx("div",{style:{flex:1,overflow:"hidden"},children:I})]})}return y});return X.jsx("div",{className:r,style:{position:"sticky",top:0,zIndex:20,display:"flex",flexDirection:"column",backgroundColor:(e==null?void 0:e.header.bg)??"#F9FAFB",borderTop:`1px solid ${(e==null?void 0:e.header.border)??"#E5E7EB"}`,borderBottom:`1px solid ${(e==null?void 0:e.header.border)??"#E5E7EB"}`,...l},children:T})}Ft.displayName="TimelineHeaders";var Bt={exports:{}};(function(t,e){(function(r,o){t.exports=o()})(Rt,function(){var r="week",o="year";return function(l,c,a){var b=c.prototype;b.week=function(f){if(f===void 0&&(f=null),f!==null)return this.add(7*(f-this.week()),"day");var v=this.$locale().yearStart||1;if(this.month()===11&&this.date()>25){var T=a(this).startOf(o).add(1,o).date(v),y=a(this).endOf(r);if(T.isBefore(y))return 1}var H=a(this).startOf(o).date(v).startOf(r).subtract(1,"millisecond"),k=this.diff(H,r,!0);return k<0?a(this).startOf("week").week():Math.ceil(k)},b.weeks=function(f){return f===void 0&&(f=null),this.week(f)}}})})(Bt);var vr=Bt.exports;const br=Dt(vr);ee.extend(br);const pr={year:30,month:30,week:20,day:15,hour:30};function Wt({unit:t,visibleTimeStart:e=0,visibleTimeEnd:r=0,canvasWidth:o=0,theme:l,height:c=28,className:a,labelFormat:b,onIntervalClick:f,minCellWidth:v,onZoomToInterval:T}){const y=u.useMemo(()=>{if(!e||!r||!o)return[];const k=r-e,M=v??pr[t];if(M>0){const O=ee(e).startOf(t);if((O.add(1,t).valueOf()-O.valueOf())/k*o<M)return[]}const I=[];let W=ee(e).startOf(t).subtract(1,t);const S=ee(r).add(2,t).valueOf();for(;W.valueOf()<S;){const O=W.add(1,t),j=W.valueOf(),N=O.valueOf(),z=(j-e)/k*o,x=(N-j)/k*o,ie=yr(W,O,t,b);I.push({start:j,end:N,label:ie,left:z,width:x}),W=O}return I},[e,r,o,t,b,v]),H=u.useCallback((k,M)=>{f?f(k,M):T&&T(k,M)},[f,T]);return y.length===0?null:X.jsx("div",{style:{display:"flex",position:"relative",height:c,overflow:"hidden"},children:y.map(k=>X.jsx("div",{className:a,onClick:()=>H(k.start,k.end),style:{position:"absolute",left:k.left,width:k.width,height:"100%",display:"flex",alignItems:"center",justifyContent:"center",borderRight:`1px solid ${(l==null?void 0:l.header.border)??"#E5E7EB"}`,borderBottom:`1px solid ${(l==null?void 0:l.header.border)??"#E5E7EB"}`,fontSize:12,color:(l==null?void 0:l.header.text)??"#6c737f",backgroundColor:(l==null?void 0:l.header.bg)??"#F9FAFB",overflow:"hidden",whiteSpace:"nowrap",cursor:"pointer",userSelect:"none",padding:"0 4px",boxSizing:"border-box"},children:X.jsx("span",{children:k.label})},k.start))})}Wt.displayName="DateHeader";function yr(t,e,r,o,l){return typeof o=="function"?o(t.toDate(),e.toDate(),r):typeof o=="string"?t.format(o):Tr(t,r)}function Tr(t,e){switch(e){case"year":return t.format("YYYY");case"month":return t.format("MM");case"week":return`${t.week()}`;case"day":return t.format("D");case"hour":return t.format("HH:mm")}}function xt({width:t,children:e,style:r}){const o=()=>({style:{width:t,...r}});return e?X.jsx(X.Fragment,{children:e({getRootProps:o})}):X.jsx("div",{style:{width:t}})}xt.displayName="SidebarHeader";function jt({children:t}){return X.jsx(X.Fragment,{children:t})}jt.displayName="CustomHeader";exports.CanvasTimeline=gr;exports.CustomHeader=jt;exports.CustomMarker=Ot;exports.DEFAULT_THEME=ae;exports.DateHeader=Wt;exports.SidebarHeader=xt;exports.TimelineHeaders=Ft;exports.TodayMarker=It;
|
|
2
|
+
//# sourceMappingURL=canvas-timeline.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-timeline.cjs.js","sources":["../src/types.ts","../src/core/ViewState.ts","../src/core/IntervalTree.ts","../src/core/LayoutEngine.ts","../src/core/HitTest.ts","../src/canvas/CanvasManager.ts","../src/canvas/GridLayer.ts","../src/canvas/DrawHelpers.ts","../src/canvas/ItemsLayer.ts","../src/canvas/OverlayLayer.ts","../src/interaction/ZoomHandler.ts","../src/interaction/InteractionHandler.ts","../node_modules/dayjs/plugin/isoWeek.js","../src/dom/Sidebar.tsx","../src/dom/TodayMarker.tsx","../src/dom/CustomMarker.tsx","../src/CanvasTimeline.tsx","../src/dom/TimelineHeaders.tsx","../node_modules/dayjs/plugin/weekOfYear.js","../src/dom/DateHeader.tsx","../src/dom/SidebarHeader.tsx","../src/dom/CustomHeader.tsx"],"sourcesContent":["import type React from 'react'\n\nexport interface Group {\n id: number | string\n title: string\n type?: string\n hierarchy?: string\n root?: boolean\n [key: string]: unknown\n}\n\nexport interface Item {\n id: number\n group: number | string\n start_time: number\n end_time: number\n type?: string\n [key: string]: unknown\n}\n\nexport interface ItemBounds {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface ItemState {\n selected: boolean\n hovered: boolean\n dragging: boolean\n filtered: boolean\n}\n\nexport interface DrawHelpers {\n roundRect(x: number, y: number, w: number, h: number, radius?: number): void\n fillText(text: string, x: number, y: number, maxWidth?: number): void\n gradient(x: number, w: number, color1: string, color2: string): CanvasGradient\n leftBar(color: string, width?: number): void\n icon(type: 'check' | 'danger-red' | 'danger-yellow', x: number, y: number, size?: number): void\n badge(text: string, x: number, y: number, bgColor: string): void\n}\n\nexport type CanvasItemRenderer = (\n ctx: CanvasRenderingContext2D,\n item: Item,\n bounds: ItemBounds,\n state: ItemState,\n helpers: DrawHelpers,\n) => void\n\nexport type CanvasGroupItemRenderer = CanvasItemRenderer\n\nexport interface DayStyle {\n backgroundColor?: string\n borderColor?: string\n opacity?: number\n}\n\nexport interface RowStyle {\n backgroundColor?: string\n borderBottomColor?: string\n}\n\nexport interface Dependency {\n fromItemId: number\n toItemId: number\n type?: 'finish-to-start' | 'start-to-start' | 'finish-to-finish'\n color?: string\n}\n\nexport interface TimelineTheme {\n primary: string\n trainColors: Record<string, string>\n status: { red: string; yellow: string; green: string }\n grid: { line: string; rowAlt: string; weekend: string }\n item: { radius: number; text: string; selectedRing: string }\n marker: { today: string; milestone: string; cursor: string }\n sidebar: { bg: string; border: string; text: string }\n header: { bg: string; border: string; text: string }\n}\n\nexport const DEFAULT_THEME: TimelineTheme = {\n primary: '#269bf7',\n trainColors: {},\n status: { red: '#EF5350', yellow: '#FBBF24', green: '#31c48d' },\n grid: { line: '#E5E5E5', rowAlt: '#F7F7F7', weekend: 'rgba(0,0,0,0.03)' },\n item: { radius: 3, text: '#374151', selectedRing: '#a3a3a3' },\n marker: { today: '#FD7171', milestone: '#3B82F6', cursor: '#269bf7' },\n sidebar: { bg: '#F9FAFB', border: '#E5E7EB', text: '#6c737f' },\n header: { bg: '#F9FAFB', border: '#E5E7EB', text: '#6c737f' },\n}\n\nexport interface MarkerConfig {\n date: number\n color: string\n width: number\n label?: string\n}\n\nexport interface CanvasTimelineProps {\n groups: Group[]\n items: Item[]\n defaultTimeStart: number\n defaultTimeEnd: number\n visibleTimeStart?: number\n visibleTimeEnd?: number\n sidebarWidth: number\n lineHeight: number\n itemHeightRatio: number\n stackItems: boolean\n buffer?: number\n canMove: boolean\n canResize: false | 'left' | 'right' | 'both'\n canChangeGroup: boolean\n dragSnap: number\n minZoom: number\n maxZoom: number\n theme?: Partial<TimelineTheme>\n dayStyle?: (date: Date) => DayStyle | null\n rowStyle?: (group: Group) => RowStyle | null\n showCursorLine?: boolean\n itemRenderer: CanvasItemRenderer\n groupRenderer?: CanvasGroupItemRenderer\n sidebarGroupRenderer: (group: Group) => React.ReactNode\n rightSidebarWidth?: number\n rightSidebarGroupRenderer?: (group: Group) => React.ReactNode\n dependencies?: Dependency[]\n onItemClick?: (itemId: number, e: PointerEvent) => void\n onItemDoubleClick?: (itemId: number, e: PointerEvent) => void\n onItemContextMenu?: (itemId: number, e: PointerEvent) => void\n onItemMove?: (itemId: number, newStartTime: number, newGroupId: string | number) => void\n onItemResize?: (itemId: number, newTime: number, edge: 'left' | 'right') => void\n /** Validate and optionally constrain move/resize. Return the (possibly modified) time. */\n moveResizeValidator?: (action: 'move' | 'resize', itemId: number, time: number, edge?: 'left' | 'right') => number\n onItemHover?: (itemId: number | null, e: PointerEvent) => void\n onCanvasDoubleClick?: (groupId: number, time: number) => void\n onCanvasContextMenu?: (groupId: number, time: number, e: PointerEvent) => void\n onTimeChange?: (start: number, end: number) => void\n onZoom?: (start: number, end: number) => void\n selected?: number[]\n /** Called when the timeline is ready, providing the capture API */\n onReady?: (api: CanvasTimelineRef) => void\n children?: React.ReactNode\n}\n\nexport interface CaptureOptions {\n timeStart: number\n timeEnd: number\n scale: number\n sidebarWidth: number\n}\n\nexport interface CanvasTimelineRef {\n captureToCanvas(options: CaptureOptions): HTMLCanvasElement\n}\n","export interface ViewStateConfig {\n visibleTimeStart: number\n visibleTimeEnd: number\n canvasWidth: number\n canvasHeight: number\n sidebarWidth: number\n lineHeight: number\n groupCount: number\n buffer: number\n scrollTop: number\n}\n\nexport class ViewState {\n visibleTimeStart: number\n visibleTimeEnd: number\n canvasWidth: number\n canvasHeight: number\n sidebarWidth: number\n lineHeight: number\n groupCount: number\n buffer: number\n scrollTop: number\n\n private visibleDuration: number\n private pixelsPerMs: number\n\n constructor(config: ViewStateConfig) {\n this.visibleTimeStart = config.visibleTimeStart\n this.visibleTimeEnd = config.visibleTimeEnd\n this.canvasWidth = config.canvasWidth\n this.canvasHeight = config.canvasHeight\n this.sidebarWidth = config.sidebarWidth\n this.lineHeight = config.lineHeight\n this.groupCount = config.groupCount\n this.buffer = config.buffer\n this.scrollTop = config.scrollTop\n\n this.visibleDuration = this.visibleTimeEnd - this.visibleTimeStart\n this.pixelsPerMs = this.canvasWidth / this.visibleDuration\n }\n\n update(params: Partial<ViewStateConfig>): void {\n if (params.visibleTimeStart !== undefined) this.visibleTimeStart = params.visibleTimeStart\n if (params.visibleTimeEnd !== undefined) this.visibleTimeEnd = params.visibleTimeEnd\n if (params.canvasWidth !== undefined) this.canvasWidth = params.canvasWidth\n if (params.canvasHeight !== undefined) this.canvasHeight = params.canvasHeight\n if (params.sidebarWidth !== undefined) this.sidebarWidth = params.sidebarWidth\n if (params.lineHeight !== undefined) this.lineHeight = params.lineHeight\n if (params.groupCount !== undefined) this.groupCount = params.groupCount\n if (params.buffer !== undefined) this.buffer = params.buffer\n if (params.scrollTop !== undefined) this.scrollTop = params.scrollTop\n\n this.visibleDuration = this.visibleTimeEnd - this.visibleTimeStart\n this.pixelsPerMs = this.canvasWidth / this.visibleDuration\n }\n\n timeToX(time: number): number {\n return (time - this.visibleTimeStart) * this.pixelsPerMs\n }\n\n xToTime(x: number): number {\n return this.visibleTimeStart + x / this.pixelsPerMs\n }\n\n yToGroupIndex(y: number): number {\n const raw = Math.floor((y + this.scrollTop) / this.lineHeight)\n return Math.max(0, Math.min(raw, this.groupCount - 1))\n }\n\n groupIndexToY(index: number): number {\n return index * this.lineHeight - this.scrollTop\n }\n\n getBufferBounds(): { bufferStart: number; bufferEnd: number } {\n const extend = this.visibleDuration * 1.5\n return {\n bufferStart: this.visibleTimeStart - extend,\n bufferEnd: this.visibleTimeEnd + extend,\n }\n }\n\n getVisibleGroupRange(): { firstVisible: number; lastVisible: number } {\n const firstVisible = Math.max(0, Math.floor(this.scrollTop / this.lineHeight))\n const visibleCount = Math.ceil(this.canvasHeight / this.lineHeight)\n const lastVisible = Math.min(this.groupCount - 1, firstVisible + visibleCount)\n return { firstVisible, lastVisible }\n }\n\n isScrollInBuffer(scrollXOffset: number): boolean {\n const bufferPixels = this.visibleDuration * 1.5 * this.pixelsPerMs\n return Math.abs(scrollXOffset) < bufferPixels\n }\n\n getTotalHeight(): number {\n return this.groupCount * this.lineHeight\n }\n}\n","interface TreeNode<T> {\n center: number\n left: TreeNode<T> | null\n right: TreeNode<T> | null\n overlapping: Array<{ item: T; start: number; end: number }>\n}\n\nexport class IntervalTree<T> {\n private root: TreeNode<T> | null = null\n\n buildFromItems(\n items: T[],\n getStart: (item: T) => number,\n getEnd: (item: T) => number,\n ): void {\n const intervals = items.map((item) => ({\n item,\n start: getStart(item),\n end: getEnd(item),\n }))\n this.root = this.buildNode(intervals)\n }\n\n private buildNode(\n intervals: Array<{ item: T; start: number; end: number }>,\n ): TreeNode<T> | null {\n if (intervals.length === 0) return null\n\n let min = Infinity\n let max = -Infinity\n for (const iv of intervals) {\n if (iv.start < min) min = iv.start\n if (iv.end > max) max = iv.end\n }\n const center = (min + max) / 2\n\n const leftIntervals: Array<{ item: T; start: number; end: number }> = []\n const rightIntervals: Array<{ item: T; start: number; end: number }> = []\n const overlapping: Array<{ item: T; start: number; end: number }> = []\n\n for (const iv of intervals) {\n if (iv.end < center) {\n leftIntervals.push(iv)\n } else if (iv.start > center) {\n rightIntervals.push(iv)\n } else {\n overlapping.push(iv)\n }\n }\n\n return {\n center,\n left: this.buildNode(leftIntervals),\n right: this.buildNode(rightIntervals),\n overlapping,\n }\n }\n\n query(start: number, end: number): T[] {\n const results: T[] = []\n this.queryNode(this.root, start, end, results)\n return results\n }\n\n private queryNode(\n node: TreeNode<T> | null,\n start: number,\n end: number,\n results: T[],\n ): void {\n if (node === null) return\n\n for (const iv of node.overlapping) {\n if (iv.start <= end && iv.end >= start) {\n results.push(iv.item)\n }\n }\n\n if (start <= node.center && node.left !== null) {\n this.queryNode(node.left, start, end, results)\n }\n\n if (end >= node.center && node.right !== null) {\n this.queryNode(node.right, start, end, results)\n }\n }\n}\n","import type { Item } from '../types'\n\nexport interface ItemLayout {\n stackLevel: number\n itemHeight: number\n}\n\nexport class LayoutEngine {\n private readonly lineHeight: number\n private readonly itemHeightRatio: number\n private layoutCache: Map<number, ItemLayout> = new Map()\n private groupMaxStack: Map<string | number, number> = new Map()\n\n constructor(lineHeight: number, itemHeightRatio: number) {\n this.lineHeight = lineHeight\n this.itemHeightRatio = itemHeightRatio\n }\n\n computeLayout(items: Item[], stackItems: boolean): Map<number, ItemLayout> {\n this.layoutCache = new Map()\n this.groupMaxStack = new Map()\n\n if (!stackItems) {\n const itemHeight = this.lineHeight * this.itemHeightRatio\n for (const item of items) {\n this.layoutCache.set(item.id, { stackLevel: 0, itemHeight })\n this.groupMaxStack.set(item.group, 0)\n }\n return this.layoutCache\n }\n\n // Group items by group id\n const byGroup = new Map<string | number, Item[]>()\n for (const item of items) {\n let arr = byGroup.get(item.group)\n if (!arr) {\n arr = []\n byGroup.set(item.group, arr)\n }\n arr.push(item)\n }\n\n const itemHeight = this.lineHeight * this.itemHeightRatio\n\n for (const [groupId, groupItems] of byGroup) {\n groupItems.sort((a, b) => {\n const d = a.start_time - b.start_time\n if (d !== 0) return d\n return (b.end_time - b.start_time) - (a.end_time - a.start_time)\n })\n\n const levelEnds: number[] = []\n let maxLevel = 0\n\n for (const item of groupItems) {\n let level = -1\n for (let i = 0; i < levelEnds.length; i++) {\n if (levelEnds[i] <= item.start_time) {\n level = i\n break\n }\n }\n\n if (level === -1) {\n level = levelEnds.length\n levelEnds.push(item.end_time)\n } else {\n levelEnds[level] = item.end_time\n }\n\n if (level > maxLevel) maxLevel = level\n\n this.layoutCache.set(item.id, { stackLevel: level, itemHeight })\n }\n\n this.groupMaxStack.set(groupId, maxLevel)\n }\n\n return this.layoutCache\n }\n\n getLayout(itemId: number): ItemLayout | undefined {\n return this.layoutCache.get(itemId)\n }\n\n getGroupHeight(groupId: string | number): number {\n const maxStack = this.groupMaxStack.get(groupId) ?? 0\n return (maxStack + 1) * this.lineHeight\n }\n}\n","import type { Item, Group } from '../types'\nimport type { ViewState } from './ViewState'\nimport type { IntervalTree } from './IntervalTree'\nimport type { LayoutEngine } from './LayoutEngine'\n\nexport function hitTest(\n canvasX: number,\n canvasY: number,\n view: ViewState,\n tree: IntervalTree<Item>,\n layout: LayoutEngine,\n groups: Group[],\n): Item | null {\n const time = view.xToTime(canvasX)\n\n const groupIndexMap = new Map<string | number, number>()\n for (let i = 0; i < groups.length; i++) {\n groupIndexMap.set(groups[i].id, i)\n }\n\n const candidates = tree.query(time, time)\n\n let topItem: Item | null = null\n let topY = -Infinity\n\n for (const item of candidates) {\n const groupIndex = groupIndexMap.get(item.group)\n if (groupIndex === undefined) continue\n\n const itemLayout = layout.getLayout(item.id)\n if (!itemLayout) continue\n\n const x = view.timeToX(item.start_time)\n const width = view.timeToX(item.end_time) - x\n\n if (canvasX < x || canvasX > x + width) continue\n\n const groupY = view.groupIndexToY(groupIndex)\n const y = groupY + itemLayout.stackLevel * view.lineHeight + (view.lineHeight - itemLayout.itemHeight) / 2\n const height = itemLayout.itemHeight\n\n if (canvasY < y || canvasY > y + height) continue\n\n if (y > topY) {\n topY = y\n topItem = item\n }\n }\n\n return topItem\n}\n\nexport function hitTestGroup(\n canvasY: number,\n view: ViewState,\n groups: Group[],\n): Group | null {\n const groupIndex = view.yToGroupIndex(canvasY)\n return groups[groupIndex] ?? null\n}\n\nexport function detectEdge(\n canvasX: number,\n item: Item,\n view: ViewState,\n threshold: number = 6,\n): 'left' | 'right' | 'body' {\n const leftX = view.timeToX(item.start_time)\n const rightX = view.timeToX(item.end_time)\n if (canvasX - leftX <= threshold) return 'left'\n if (rightX - canvasX <= threshold) return 'right'\n return 'body'\n}\n","/**\n * Resize the canvas buffer only when dimensions actually change.\n * Setting canvas.width/height is destructive (clears buffer + resets state),\n * so we avoid it unless necessary.\n */\nexport function setupCanvas(\n canvas: HTMLCanvasElement,\n width: number,\n height: number,\n): CanvasRenderingContext2D {\n const dpr = window.devicePixelRatio || 1\n const targetW = Math.round(width * dpr)\n const targetH = Math.round(height * dpr)\n\n if (canvas.width !== targetW || canvas.height !== targetH) {\n canvas.width = targetW\n canvas.height = targetH\n canvas.style.width = `${width}px`\n canvas.style.height = `${height}px`\n }\n\n const ctx = canvas.getContext('2d')!\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0)\n return ctx\n}\n\nexport function clearCanvas(ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement): void {\n const dpr = window.devicePixelRatio || 1\n ctx.clearRect(0, 0, canvas.width / dpr, canvas.height / dpr)\n}\n\nexport type LayerName = 'grid' | 'items' | 'overlay'\n\nexport interface DirtyFlags {\n grid: boolean\n items: boolean\n overlay: boolean\n}\n\nexport class RenderScheduler {\n private dirty: DirtyFlags = { grid: false, items: false, overlay: false }\n private rafId: number | null = null\n private drawCallback: (flags: DirtyFlags) => void\n\n constructor(drawCallback: (flags: DirtyFlags) => void) {\n this.drawCallback = drawCallback\n }\n\n markDirty(layer: LayerName): void {\n this.dirty[layer] = true\n this.schedule()\n }\n\n markAllDirty(): void {\n this.dirty.grid = true\n this.dirty.items = true\n this.dirty.overlay = true\n this.schedule()\n }\n\n dispose(): void {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId)\n this.rafId = null\n }\n }\n\n private schedule(): void {\n if (this.rafId !== null) return\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null\n const flags = { ...this.dirty }\n this.dirty.grid = false\n this.dirty.items = false\n this.dirty.overlay = false\n this.drawCallback(flags)\n })\n }\n}\n","import dayjs from 'dayjs'\nimport type { Group, TimelineTheme, DayStyle, RowStyle } from '../types'\nimport type { ViewState } from '../core/ViewState'\n\nexport class GridLayer {\n draw(\n ctx: CanvasRenderingContext2D,\n view: ViewState,\n groups: Group[],\n theme: TimelineTheme,\n dayStyle?: (date: Date) => DayStyle | null,\n rowStyle?: (group: Group) => RowStyle | null,\n ): void {\n const { firstVisible, lastVisible } = view.getVisibleGroupRange()\n\n // Draw row backgrounds\n for (let i = firstVisible; i <= lastVisible; i++) {\n const y = view.groupIndexToY(i)\n const group = groups[i]\n if (!group) continue\n\n let bgColor: string\n const customRow = rowStyle?.(group)\n if (customRow?.backgroundColor) {\n bgColor = customRow.backgroundColor\n } else {\n bgColor = i % 2 === 0 ? '#FFFFFF' : theme.grid.rowAlt\n }\n\n ctx.fillStyle = bgColor\n ctx.fillRect(0, y, view.canvasWidth, view.lineHeight)\n\n // Row separator\n ctx.strokeStyle = customRow?.borderBottomColor ?? theme.grid.line\n ctx.lineWidth = 0.5\n ctx.beginPath()\n ctx.moveTo(0, y + view.lineHeight)\n ctx.lineTo(view.canvasWidth, y + view.lineHeight)\n ctx.stroke()\n }\n\n // Draw day columns, backgrounds, and vertical grid lines\n const visibleStart = view.visibleTimeStart\n const visibleEnd = view.visibleTimeEnd\n const visibleDuration = visibleEnd - visibleStart\n const dayMs = 86400000\n const dayPixelWidth = (dayMs / visibleDuration) * view.canvasWidth\n\n // Determine grid line interval based on zoom level\n let stepUnit: 'day' | 'week' | 'month' = 'day'\n if (dayPixelWidth < 2) stepUnit = 'month'\n else if (dayPixelWidth < 8) stepUnit = 'week'\n\n // Draw day backgrounds (dayStyle + weekends) — batch consecutive same-style days\n if (dayStyle || true) { // always draw weekends\n let current = dayjs(visibleStart).startOf('day')\n const end = dayjs(visibleEnd).endOf('day')\n\n // Batch: track current fill color and start x\n let batchColor: string | null = null\n let batchOpacity = 1\n let batchStartX = 0\n const customBorderLines: { x: number; color: string }[] = []\n\n const flushBatch = (endX: number) => {\n if (batchColor !== null) {\n ctx.fillStyle = batchColor\n if (batchOpacity !== 1) ctx.globalAlpha = batchOpacity\n ctx.fillRect(batchStartX, 0, endX - batchStartX, view.canvasHeight)\n if (batchOpacity !== 1) ctx.globalAlpha = 1\n batchColor = null\n batchOpacity = 1\n }\n }\n\n while (current.isBefore(end)) {\n const x = view.timeToX(current.valueOf())\n\n const date = current.toDate()\n const custom = dayStyle?.(date)\n let color: string | null = null\n let opacity = 1\n\n if (custom?.backgroundColor) {\n color = custom.backgroundColor\n opacity = custom.opacity ?? 1\n } else {\n const dow = current.day()\n if (dow === 0 || dow === 6) {\n color = theme.grid.weekend\n }\n }\n\n // Collect custom border colors for later drawing\n if (custom?.borderColor) {\n customBorderLines.push({ x, color: custom.borderColor })\n }\n\n // Batch consecutive same-color fills\n if (color === batchColor && opacity === batchOpacity) {\n // extend batch\n } else {\n flushBatch(x)\n if (color !== null) {\n batchColor = color\n batchOpacity = opacity\n batchStartX = x\n }\n }\n\n current = current.add(1, 'day')\n }\n // Flush remaining batch\n if (batchColor !== null) {\n flushBatch(view.timeToX(current.valueOf()))\n }\n\n // Draw custom border lines from dayStyle\n for (const line of customBorderLines) {\n ctx.strokeStyle = line.color\n ctx.lineWidth = 0.5\n ctx.beginPath()\n ctx.moveTo(line.x, 0)\n ctx.lineTo(line.x, view.canvasHeight)\n ctx.stroke()\n }\n }\n\n // Draw vertical grid lines at appropriate interval\n let current = dayjs(visibleStart).startOf(stepUnit)\n const end = dayjs(visibleEnd).add(1, stepUnit)\n\n ctx.strokeStyle = theme.grid.line\n ctx.lineWidth = 0.5\n ctx.beginPath()\n while (current.isBefore(end)) {\n const x = view.timeToX(current.valueOf())\n ctx.moveTo(x, 0)\n ctx.lineTo(x, view.canvasHeight)\n current = current.add(1, stepUnit)\n }\n ctx.stroke()\n }\n}\n","import type { DrawHelpers, ItemBounds } from '../types'\n\nconst ITEM_FONT = '500 12px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif'\n\n/**\n * Creates a DrawHelpers object bound to the given canvas context and optional item bounds.\n * These helpers are passed to every itemRenderer call to simplify common canvas operations.\n */\nexport function createDrawHelpers(\n ctx: CanvasRenderingContext2D,\n bounds?: ItemBounds,\n): DrawHelpers {\n return {\n /**\n * Draws a filled rounded rectangle.\n * Default corner radius is 3px.\n */\n roundRect(x: number, y: number, w: number, h: number, radius = 3): void {\n ctx.beginPath()\n ctx.roundRect(x, y, w, h, radius)\n ctx.fill()\n },\n\n /**\n * Draws text at (x, y) using the standard item font.\n * If maxWidth is provided and the text is too wide, binary-search truncates it\n * and appends '...' so it fits within maxWidth.\n */\n fillText(text: string, x: number, y: number, maxWidth?: number): void {\n ctx.font = ITEM_FONT\n\n if (maxWidth !== undefined && ctx.measureText(text).width > maxWidth) {\n // Binary-search for the longest prefix that fits with '...' appended\n let lo = 0\n let hi = text.length\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2)\n const candidate = text.slice(0, mid) + '...'\n if (ctx.measureText(candidate).width <= maxWidth) {\n lo = mid\n } else {\n hi = mid - 1\n }\n }\n ctx.fillText(text.slice(0, lo) + '...', x, y)\n } else {\n ctx.fillText(text, x, y)\n }\n },\n\n /**\n * Creates a 50/50 linear gradient from color1 (0%–50%) to color2 (50%–100%)\n * spanning the given x position and width.\n */\n gradient(x: number, w: number, color1: string, color2: string): CanvasGradient {\n const grad = ctx.createLinearGradient(x, 0, x + w, 0)\n grad.addColorStop(0, color1)\n grad.addColorStop(0.5, color1)\n grad.addColorStop(0.5, color2)\n grad.addColorStop(1, color2)\n return grad\n },\n\n /**\n * Draws a vertical colored bar on the left edge of the item bounds.\n * Does nothing if no bounds were provided.\n */\n leftBar(color: string, width = 3): void {\n if (!bounds) return\n ctx.save()\n ctx.fillStyle = color\n ctx.fillRect(bounds.x, bounds.y, width, bounds.height)\n ctx.restore()\n },\n\n /**\n * Draws a vector icon centered at (x, y).\n * Supported types: 'check', 'danger-red', 'danger-yellow'.\n * Default size is 14px.\n */\n icon(type: 'check' | 'danger-red' | 'danger-yellow', x: number, y: number, size = 14): void {\n ctx.save()\n const half = size / 2\n\n if (type === 'check') {\n // Green circle with white checkmark\n ctx.fillStyle = '#31c48d'\n ctx.beginPath()\n ctx.arc(x + half, y + half, half, 0, Math.PI * 2)\n ctx.fill()\n\n // Draw checkmark path\n ctx.strokeStyle = '#ffffff'\n ctx.lineWidth = size * 0.12\n ctx.beginPath()\n const cx = x + half\n const cy = y + half\n ctx.moveTo(cx - half * 0.45, cy)\n ctx.lineTo(cx - half * 0.1, cy + half * 0.42)\n ctx.lineTo(cx + half * 0.45, cy - half * 0.35)\n ctx.stroke()\n } else if (type === 'danger-red' || type === 'danger-yellow') {\n const fillColor = type === 'danger-red' ? '#EF5350' : '#FBBF24'\n\n // Triangle background\n ctx.fillStyle = fillColor\n ctx.beginPath()\n ctx.moveTo(x + half, y) // top-center\n ctx.lineTo(x + size, y + size) // bottom-right\n ctx.lineTo(x, y + size) // bottom-left\n ctx.closePath()\n ctx.fill()\n\n // Exclamation mark stem\n ctx.fillStyle = '#ffffff'\n const stemW = size * 0.12\n const stemX = x + half - stemW / 2\n ctx.fillRect(stemX, y + size * 0.35, stemW, size * 0.35)\n\n // Exclamation mark dot\n ctx.beginPath()\n ctx.arc(x + half, y + size * 0.82, stemW * 0.7, 0, Math.PI * 2)\n ctx.fill()\n }\n\n ctx.restore()\n },\n\n /**\n * Draws a pill-shaped badge with centered white text on a colored background.\n */\n badge(text: string, x: number, y: number, bgColor: string): void {\n ctx.save()\n\n // Measure text to size the pill\n ctx.font = ITEM_FONT\n const textMetrics = ctx.measureText(text)\n const textWidth = textMetrics.width\n const paddingH = 8\n const paddingV = 3\n const pillHeight = 12 + paddingV * 2\n const pillWidth = textWidth + paddingH * 2\n const radius = pillHeight / 2\n\n // Draw pill background\n ctx.fillStyle = bgColor\n ctx.beginPath()\n ctx.roundRect(x, y, pillWidth, pillHeight, radius)\n ctx.fill()\n\n // Draw centered white text\n ctx.fillStyle = '#ffffff'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText(text, x + pillWidth / 2, y + pillHeight / 2)\n\n ctx.restore()\n },\n }\n}\n","import type {\n Item, Group, TimelineTheme, CanvasItemRenderer, CanvasGroupItemRenderer,\n Dependency, ItemBounds, ItemState,\n} from '../types'\nimport type { ViewState } from '../core/ViewState'\nimport type { IntervalTree } from '../core/IntervalTree'\nimport type { LayoutEngine } from '../core/LayoutEngine'\nimport { createDrawHelpers } from './DrawHelpers'\n\nexport class ItemsLayer {\n draw(\n ctx: CanvasRenderingContext2D,\n view: ViewState,\n groups: Group[],\n _items: Item[],\n tree: IntervalTree<Item>,\n layout: LayoutEngine,\n itemRenderer: CanvasItemRenderer,\n groupRenderer: CanvasGroupItemRenderer | undefined,\n theme: TimelineTheme,\n selected: number[],\n hoveredItemId: number | undefined,\n dependencies?: Dependency[],\n ): void {\n // Query only visible time range + small padding (not the full 4x buffer)\n const padding = (view.visibleTimeEnd - view.visibleTimeStart) * 0.1\n const queryStart = view.visibleTimeStart - padding\n const queryEnd = view.visibleTimeEnd + padding\n const visibleItems = tree.query(queryStart, queryEnd)\n\n const groupIndexMap = new Map<string | number, number>()\n for (let i = 0; i < groups.length; i++) {\n groupIndexMap.set(groups[i].id, i)\n }\n\n const selectedSet = new Set(selected)\n const itemBoundsMap = new Map<number, ItemBounds>()\n\n // Vertical culling bounds\n const yMin = -view.lineHeight\n const yMax = view.canvasHeight + view.lineHeight\n\n for (const item of visibleItems) {\n const groupIndex = groupIndexMap.get(item.group)\n if (groupIndex === undefined) continue\n\n const itemLayout = layout.getLayout(item.id)\n if (!itemLayout) continue\n\n const groupY = view.groupIndexToY(groupIndex)\n const y = groupY + itemLayout.stackLevel * view.lineHeight + (view.lineHeight - itemLayout.itemHeight) / 2\n\n // Skip items that are entirely off-screen vertically\n const height = itemLayout.itemHeight\n if (y + height < yMin || y > yMax) continue\n\n const x = view.timeToX(item.start_time)\n const width = view.timeToX(item.end_time) - x\n\n const bounds: ItemBounds = { x, y, width, height }\n itemBoundsMap.set(item.id, bounds)\n\n const state: ItemState = {\n selected: selectedSet.has(item.id),\n hovered: hoveredItemId === item.id,\n dragging: false,\n filtered: item.filtered !== false,\n }\n\n ctx.save()\n const helpers = createDrawHelpers(ctx, bounds)\n const renderer = groupRenderer && (item.type === 'control_area_group' || item.type === 'construction_train')\n ? groupRenderer\n : itemRenderer\n renderer(ctx, item, bounds, state, helpers)\n ctx.restore()\n }\n\n if (dependencies && dependencies.length > 0) {\n this.drawDependencies(ctx, dependencies, itemBoundsMap, hoveredItemId, theme)\n }\n }\n\n private drawDependencies(\n ctx: CanvasRenderingContext2D,\n dependencies: Dependency[],\n boundsMap: Map<number, ItemBounds>,\n hoveredItemId: number | undefined,\n theme: TimelineTheme,\n ): void {\n for (const dep of dependencies) {\n const fromBounds = boundsMap.get(dep.fromItemId)\n const toBounds = boundsMap.get(dep.toItemId)\n if (!fromBounds || !toBounds) continue\n\n const isHighlighted = hoveredItemId === dep.fromItemId || hoveredItemId === dep.toItemId\n\n ctx.strokeStyle = isHighlighted ? theme.primary : (dep.color ?? '#94A3B8')\n ctx.lineWidth = isHighlighted ? 2 : 1.5\n ctx.setLineDash([])\n\n const startX = fromBounds.x + fromBounds.width\n const startY = fromBounds.y + fromBounds.height / 2\n const endX = toBounds.x\n const endY = toBounds.y + toBounds.height / 2\n\n const dx = Math.abs(endX - startX)\n const cpOffset = Math.max(dx * 0.4, 30)\n\n ctx.beginPath()\n ctx.moveTo(startX, startY)\n ctx.bezierCurveTo(startX + cpOffset, startY, endX - cpOffset, endY, endX, endY)\n ctx.stroke()\n\n // Arrowhead\n const arrowSize = 6\n ctx.fillStyle = ctx.strokeStyle\n ctx.beginPath()\n ctx.moveTo(endX, endY)\n ctx.lineTo(endX - arrowSize, endY - arrowSize / 2)\n ctx.lineTo(endX - arrowSize, endY + arrowSize / 2)\n ctx.closePath()\n ctx.fill()\n }\n }\n}\n","import type { TimelineTheme, MarkerConfig, ItemBounds, Item, CanvasItemRenderer } from '../types'\nimport type { ViewState } from '../core/ViewState'\nimport type { InteractionMode } from '../interaction/InteractionHandler'\nimport { createDrawHelpers } from './DrawHelpers'\n\nexport interface InteractionRenderState {\n item: Item\n mode: InteractionMode\n bounds: ItemBounds\n renderer: CanvasItemRenderer\n targetGroupY?: number\n groupChanged?: boolean\n}\n\nexport interface OverlayDrawOptions {\n cursorX: number | null\n snapX?: number | null\n markers?: MarkerConfig[]\n interaction?: InteractionRenderState | null\n}\n\nexport class OverlayLayer {\n draw(\n ctx: CanvasRenderingContext2D,\n view: ViewState,\n theme: TimelineTheme,\n options: OverlayDrawOptions,\n ): void {\n const { cursorX, snapX, markers, interaction } = options\n\n // Draw markers\n if (markers) {\n for (const marker of markers) {\n const x = view.timeToX(marker.date)\n\n ctx.fillStyle = marker.color\n ctx.fillRect(x - marker.width / 2, 0, marker.width, view.canvasHeight)\n\n if (marker.label) {\n ctx.save()\n ctx.font = '500 10px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif'\n const textWidth = ctx.measureText(marker.label).width\n const padding = 8\n const maxBadgeWidth = 200\n const badgeWidth = Math.min(textWidth + padding * 2, maxBadgeWidth)\n const badgeHeight = 20\n const badgeX = x - badgeWidth / 2\n const badgeY = 4\n\n ctx.fillStyle = marker.color\n ctx.beginPath()\n ctx.roundRect(badgeX, badgeY, badgeWidth, badgeHeight, 3)\n ctx.fill()\n\n ctx.fillStyle = '#FFFFFF'\n ctx.textBaseline = 'middle'\n const maxTextWidth = maxBadgeWidth - padding * 2\n const displayText = textWidth > maxTextWidth\n ? marker.label.slice(0, Math.floor(marker.label.length * maxTextWidth / textWidth)) + '…'\n : marker.label\n ctx.fillText(displayText, badgeX + padding, badgeY + badgeHeight / 2)\n ctx.restore()\n }\n }\n }\n\n // Draw cursor line\n if (cursorX !== null && cursorX !== undefined) {\n ctx.strokeStyle = theme.marker.cursor\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(cursorX, 0)\n ctx.lineTo(cursorX, view.canvasHeight)\n ctx.stroke()\n }\n\n // Draw snap guide line\n if (snapX !== null && snapX !== undefined) {\n ctx.strokeStyle = theme.primary\n ctx.lineWidth = 1\n ctx.setLineDash([4, 4])\n ctx.beginPath()\n ctx.moveTo(snapX, 0)\n ctx.lineTo(snapX, view.canvasHeight)\n ctx.stroke()\n ctx.setLineDash([])\n }\n\n // Draw interaction ghost (move, resize-left, resize-right)\n if (interaction) {\n // Group highlight band when moving to a different group\n if (interaction.groupChanged && interaction.targetGroupY !== undefined) {\n ctx.fillStyle = 'rgba(59, 130, 246, 0.08)'\n ctx.fillRect(0, interaction.targetGroupY, view.canvasWidth, view.lineHeight)\n }\n\n ctx.save()\n ctx.globalAlpha = 0.5\n const helpers = createDrawHelpers(ctx, interaction.bounds)\n interaction.renderer(\n ctx, interaction.item, interaction.bounds,\n { selected: false, hovered: false, dragging: true, filtered: true },\n helpers,\n )\n ctx.restore()\n }\n }\n}\n","const MAX_DELTA = 120\n\n/**\n * Normalize wheel delta across browsers/platforms.\n * deltaMode 0 = pixels, 1 = lines (×15), 2 = pages (×800).\n * Clamp to ±120 to prevent erratic jumps.\n */\nfunction normalizeDelta(e: WheelEvent): number {\n let delta = e.deltaY || e.deltaX\n if (e.deltaMode === 1) delta *= 15\n else if (e.deltaMode === 2) delta *= 800\n return Math.max(-MAX_DELTA, Math.min(MAX_DELTA, delta))\n}\n\nexport class ZoomHandler {\n private onZoom: (newStart: number, newEnd: number) => void\n private visibleTimeStart: number\n private visibleTimeEnd: number\n private minZoom: number\n private maxZoom: number\n\n constructor(\n onZoom: (newStart: number, newEnd: number) => void,\n visibleTimeStart: number,\n visibleTimeEnd: number,\n minZoom: number,\n maxZoom: number,\n ) {\n this.onZoom = onZoom\n this.visibleTimeStart = visibleTimeStart\n this.visibleTimeEnd = visibleTimeEnd\n this.minZoom = minZoom\n this.maxZoom = maxZoom\n }\n\n updateBounds(start: number, end: number): void {\n this.visibleTimeStart = start\n this.visibleTimeEnd = end\n }\n\n handleWheelZoom(e: WheelEvent, cursorRatio: number): void {\n const delta = normalizeDelta(e)\n // Speed: ctrlKey (trackpad pinch) = 10, metaKey = 3, altKey = 1\n const speed = e.ctrlKey ? 10 : e.metaKey ? 3 : 1\n\n // Reciprocal formula for symmetric zoom-in / zoom-out\n const scale = delta > 0\n ? 1.0 + (speed * delta) / 500\n : 1.0 / (1.0 + (speed * -delta) / 500)\n\n const currentDuration = this.visibleTimeEnd - this.visibleTimeStart\n let newDuration = Math.round(currentDuration * scale)\n newDuration = Math.max(this.minZoom, Math.min(this.maxZoom, newDuration))\n\n const newStart = Math.round(this.visibleTimeStart + (currentDuration - newDuration) * cursorRatio)\n const newEnd = newStart + newDuration\n\n this.onZoom(newStart, newEnd)\n }\n}\n","import type { Item } from '../types'\n\nconst ACTIVATION_THRESHOLD = 4\n\nexport type InteractionMode = 'move' | 'resize-left' | 'resize-right'\n\nexport interface InteractionState {\n item: Item\n mode: InteractionMode\n startX: number\n startY: number\n currentX: number\n currentY: number\n deltaX: number\n originalGroup: string | number\n currentGroup: string | number\n}\n\nexport class InteractionHandler {\n private state: InteractionState | null = null\n private dragSnap: number\n private activated = false\n\n constructor(dragSnap: number) {\n this.dragSnap = dragSnap\n }\n\n startInteraction(item: Item, mode: InteractionMode, x: number, y: number): void {\n this.state = {\n item, mode, startX: x, startY: y, currentX: x, currentY: y,\n deltaX: 0, originalGroup: item.group, currentGroup: item.group,\n }\n this.activated = false\n }\n\n update(x: number, y: number): void {\n if (!this.state) return\n this.state.currentX = x\n this.state.currentY = y\n this.state.deltaX = x - this.state.startX\n if (!this.activated && Math.abs(this.state.deltaX) >= ACTIVATION_THRESHOLD) {\n this.activated = true\n }\n }\n\n setCurrentGroup(groupId: string | number): void {\n if (this.state) this.state.currentGroup = groupId\n }\n\n endMove(pixelsPerMs: number): { newStartTime: number; newGroupId: string | number } | null {\n if (!this.state) return null\n const deltaMs = this.state.deltaX / pixelsPerMs\n const newStartTime = this.state.item.start_time + deltaMs\n const snapped = Math.round(newStartTime / this.dragSnap) * this.dragSnap\n const newGroupId = this.state.currentGroup\n this.state = null\n this.activated = false\n return { newStartTime: snapped, newGroupId }\n }\n\n endResize(pixelsPerMs: number): { newTime: number; edge: 'left' | 'right' } | null {\n if (!this.state) return null\n const deltaMs = this.state.deltaX / pixelsPerMs\n const edge = this.state.mode === 'resize-left' ? 'left' as const : 'right' as const\n const baseTime = edge === 'left' ? this.state.item.start_time : this.state.item.end_time\n const newTime = baseTime + deltaMs\n const snapped = Math.round(newTime / this.dragSnap) * this.dragSnap\n this.state = null\n this.activated = false\n return { newTime: snapped, edge }\n }\n\n cancel(): void {\n this.state = null\n this.activated = false\n }\n\n getState(): InteractionState | null {\n return this.state\n }\n\n getMode(): InteractionMode | null {\n return this.state?.mode ?? null\n }\n\n isActive(): boolean {\n return this.state !== null && this.activated\n }\n\n isPending(): boolean {\n return this.state !== null\n }\n}\n","!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_plugin_isoWeek=t()}(this,(function(){\"use strict\";var e=\"day\";return function(t,i,s){var a=function(t){return t.add(4-t.isoWeekday(),e)},d=i.prototype;d.isoWeekYear=function(){return a(this).year()},d.isoWeek=function(t){if(!this.$utils().u(t))return this.add(7*(t-this.isoWeek()),e);var i,d,n,o,r=a(this),u=(i=this.isoWeekYear(),d=this.$u,n=(d?s.utc:s)().year(i).startOf(\"year\"),o=4-n.isoWeekday(),n.isoWeekday()>4&&(o+=7),n.add(o,e));return r.diff(u,\"week\")+1},d.isoWeekday=function(e){return this.$utils().u(e)?this.day()||7:this.day(this.day()%7?e:e-7)};var n=d.startOf;d.startOf=function(e,t){var i=this.$utils(),s=!!i.u(t)||t;return\"isoweek\"===i.p(e)?s?this.date(this.date()-(this.isoWeekday()-1)).startOf(\"day\"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf(\"day\"):n.bind(this)(e,t)}}}));","import React, { useRef, useCallback, useEffect } from 'react'\nimport type { Group, TimelineTheme } from '../types'\n\ninterface SidebarProps {\n groups: Group[]\n width: number\n lineHeight: number\n scrollTop: number\n canvasHeight: number\n theme: TimelineTheme\n groupRenderer: (group: Group) => React.ReactNode\n onScroll: (scrollTop: number) => void\n}\n\nconst OVERSCAN = 5\n\nexport function Sidebar({\n groups, width, lineHeight, scrollTop, canvasHeight, theme, groupRenderer, onScroll,\n}: SidebarProps) {\n const containerRef = useRef<HTMLDivElement>(null)\n const isScrollingRef = useRef(false)\n const totalHeight = groups.length * lineHeight\n const displayHeight = canvasHeight\n\n const firstVisible = Math.max(0, Math.floor(scrollTop / lineHeight) - OVERSCAN)\n const lastVisible = Math.min(groups.length - 1, Math.ceil((scrollTop + canvasHeight) / lineHeight) + OVERSCAN)\n\n const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {\n if (isScrollingRef.current) return\n onScroll(e.currentTarget.scrollTop)\n }, [onScroll])\n\n useEffect(() => {\n if (containerRef.current) {\n isScrollingRef.current = true\n containerRef.current.scrollTop = scrollTop\n requestAnimationFrame(() => { isScrollingRef.current = false })\n }\n }, [scrollTop])\n\n const visibleGroups = []\n for (let i = firstVisible; i <= lastVisible; i++) {\n const group = groups[i]\n if (!group) continue\n visibleGroups.push(\n <div\n key={group.id}\n style={{\n position: 'absolute',\n top: i * lineHeight,\n height: lineHeight,\n width: '100%',\n overflow: 'hidden',\n display: 'flex',\n alignItems: 'stretch',\n borderBottom: `1px solid ${theme.grid?.line ?? '#E5E5E5'}`,\n boxSizing: 'border-box',\n }}\n >\n {groupRenderer(group)}\n </div>,\n )\n }\n\n return (\n <div\n ref={containerRef}\n onScroll={handleScroll}\n style={{\n width,\n height: displayHeight,\n overflowY: totalHeight > canvasHeight ? 'auto' : 'hidden',\n overflowX: 'hidden',\n position: 'relative',\n borderRight: `1px solid ${theme.sidebar.border}`,\n backgroundColor: theme.sidebar.bg,\n }}\n >\n <div style={{ height: totalHeight, position: 'relative' }}>{visibleGroups}</div>\n </div>\n )\n}\n","import type { MarkerConfig } from '../types'\n\ninterface TodayMarkerProps {\n color?: string\n width?: number\n label?: string\n /** Auto-update interval in ms. Default 10000 (10s). Set 0 to disable. */\n interval?: number\n}\n\nexport function TodayMarker(_props: TodayMarkerProps) { return null }\nTodayMarker.displayName = 'TodayMarker'\n\nexport function getTodayMarkerConfig(props: TodayMarkerProps): MarkerConfig {\n // Snap to current minute to avoid unnecessary redraws\n const now = Math.floor(Date.now() / 60000) * 60000\n return { date: now, color: props.color ?? '#FD7171', width: props.width ?? 6, label: props.label }\n}\n\nexport function getTodayMarkerInterval(props: TodayMarkerProps): number {\n return props.interval ?? 10000\n}\n","import type { MarkerConfig } from '../types'\n\ninterface CustomMarkerProps {\n date: number\n color?: string\n width?: number\n label?: string\n}\n\nexport function CustomMarker(_props: CustomMarkerProps) { return null }\nCustomMarker.displayName = 'CustomMarker'\n\nexport function getCustomMarkerConfig(props: CustomMarkerProps): MarkerConfig {\n return {\n date: props.date,\n color: props.color ?? '#3B82F6',\n width: props.width ?? 4,\n label: props.label,\n }\n}\n","import React, { useRef, useEffect, useState, useCallback, useMemo, useImperativeHandle, forwardRef } from 'react'\nimport { flushSync } from 'react-dom'\nimport type {\n CanvasTimelineProps,\n CanvasTimelineRef,\n MarkerConfig,\n TimelineTheme,\n} from './types'\nimport { DEFAULT_THEME } from './types'\nimport { ViewState } from './core/ViewState'\nimport { IntervalTree } from './core/IntervalTree'\nimport { LayoutEngine } from './core/LayoutEngine'\nimport { hitTest, hitTestGroup } from './core/HitTest'\nimport { setupCanvas, clearCanvas, RenderScheduler } from './canvas/CanvasManager'\nimport { GridLayer } from './canvas/GridLayer'\nimport { ItemsLayer } from './canvas/ItemsLayer'\nimport { OverlayLayer } from './canvas/OverlayLayer'\nimport { ZoomHandler } from './interaction/ZoomHandler'\nimport { InteractionHandler } from './interaction/InteractionHandler'\nimport { detectEdge } from './core/HitTest'\nimport dayjs from 'dayjs'\nimport isoWeek from 'dayjs/plugin/isoWeek'\nimport { Sidebar } from './dom/Sidebar'\nimport { getTodayMarkerConfig, getTodayMarkerInterval } from './dom/TodayMarker'\nimport { getCustomMarkerConfig } from './dom/CustomMarker'\n\ndayjs.extend(isoWeek)\n\nfunction mergeTheme(partial?: Partial<TimelineTheme>): TimelineTheme {\n if (!partial) return DEFAULT_THEME\n return {\n ...DEFAULT_THEME,\n ...partial,\n status: { ...DEFAULT_THEME.status, ...partial.status },\n grid: { ...DEFAULT_THEME.grid, ...partial.grid },\n item: { ...DEFAULT_THEME.item, ...partial.item },\n marker: { ...DEFAULT_THEME.marker, ...partial.marker },\n sidebar: { ...DEFAULT_THEME.sidebar, ...partial.sidebar },\n header: { ...DEFAULT_THEME.header, ...partial.header },\n }\n}\n\nconst HEADER_THROTTLE_MS = 32\n\nexport const CanvasTimeline = React.memo(forwardRef<CanvasTimelineRef, CanvasTimelineProps>(function CanvasTimeline(props, ref) {\n const {\n groups,\n items,\n defaultTimeStart,\n defaultTimeEnd,\n sidebarWidth,\n lineHeight,\n itemHeightRatio,\n stackItems,\n canMove,\n canChangeGroup,\n canResize,\n dragSnap,\n minZoom,\n maxZoom,\n theme: themePartial,\n dayStyle,\n rowStyle,\n showCursorLine,\n itemRenderer,\n groupRenderer,\n sidebarGroupRenderer,\n dependencies,\n onItemClick,\n onItemDoubleClick,\n onItemContextMenu,\n onItemMove,\n onItemResize,\n moveResizeValidator,\n onItemHover,\n onCanvasDoubleClick,\n onCanvasContextMenu,\n onTimeChange,\n onZoom,\n selected: selectedProp = [],\n rightSidebarWidth,\n rightSidebarGroupRenderer,\n onReady,\n children,\n } = props\n\n const theme = useMemo(() => mergeTheme(themePartial), [themePartial])\n\n const getGroupIndex = useCallback((groupId: string | number, grps: typeof groups) => {\n for (let i = 0; i < grps.length; i++) {\n if (grps[i].id === groupId) return i\n }\n return 0\n }, [])\n\n const selectedKey = selectedProp.join(',')\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const selected = useMemo(() => selectedProp, [selectedKey])\n\n const gridCanvasRef = useRef<HTMLCanvasElement>(null)\n const itemsCanvasRef = useRef<HTMLCanvasElement>(null)\n const overlayCanvasRef = useRef<HTMLCanvasElement>(null)\n const interactionRef = useRef<HTMLDivElement>(null)\n const outerRef = useRef<HTMLDivElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n\n const [containerSize, setContainerSize] = useState({ width: 800, height: 600 })\n\n useEffect(() => {\n const container = outerRef.current\n if (!container) return\n const obs = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry) {\n setContainerSize({ width: entry.contentRect.width, height: entry.contentRect.height })\n }\n })\n obs.observe(container)\n return () => obs.disconnect()\n }, [])\n\n const canvasWidth = Math.max(0, containerSize.width - sidebarWidth - (rightSidebarWidth ?? 0))\n const canvasHeight = groups.length * lineHeight || containerSize.height\n\n // --- MUTABLE VIEW STATE (hot path) ---\n const viewStateRef = useRef<ViewState>(\n new ViewState({\n visibleTimeStart: props.visibleTimeStart ?? defaultTimeStart,\n visibleTimeEnd: props.visibleTimeEnd ?? defaultTimeEnd,\n canvasWidth,\n canvasHeight,\n sidebarWidth,\n lineHeight,\n groupCount: groups.length,\n buffer: props.buffer ?? 3,\n scrollTop: 0,\n }),\n )\n\n const cursorXRef = useRef<number | null>(null)\n const hoveredItemIdRef = useRef<number | undefined>(undefined)\n\n // --- THROTTLED HEADER STATE ---\n const [headerTimeStart, setHeaderTimeStart] = useState(props.visibleTimeStart ?? defaultTimeStart)\n const [headerTimeEnd, setHeaderTimeEnd] = useState(props.visibleTimeEnd ?? defaultTimeEnd)\n const [sidebarScrollTop, setSidebarScrollTop] = useState(0)\n const headerTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const syncHeaderState = useCallback(() => {\n const vs = viewStateRef.current\n setHeaderTimeStart(vs.visibleTimeStart)\n setHeaderTimeEnd(vs.visibleTimeEnd)\n setSidebarScrollTop(vs.scrollTop)\n headerTimerRef.current = null\n }, [])\n\n const scheduleHeaderSync = useCallback(() => {\n if (headerTimerRef.current !== null) return\n headerTimerRef.current = setTimeout(syncHeaderState, HEADER_THROTTLE_MS)\n }, [syncHeaderState])\n\n useEffect(() => {\n return () => { if (headerTimerRef.current !== null) clearTimeout(headerTimerRef.current) }\n }, [])\n\n // --- CORE DATA STRUCTURES ---\n const intervalTree = useMemo(() => {\n const tree = new IntervalTree<(typeof items)[0]>()\n tree.buildFromItems(items, (i) => i.start_time, (i) => i.end_time)\n return tree\n }, [items])\n\n const layoutEngine = useMemo(() => {\n const engine = new LayoutEngine(lineHeight, itemHeightRatio)\n engine.computeLayout(items, stackItems)\n return engine\n }, [items, lineHeight, itemHeightRatio, stackItems])\n\n const gridLayer = useMemo(() => new GridLayer(), [])\n const itemsLayer = useMemo(() => new ItemsLayer(), [])\n const overlayLayer = useMemo(() => new OverlayLayer(), [])\n const interactionHandler = useMemo(() => new InteractionHandler(dragSnap), [dragSnap])\n\n // --- MARKERS ---\n const markerConfigs = useMemo(() => {\n const configs: MarkerConfig[] = []\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return\n const displayName = (child.type as { displayName?: string })?.displayName\n if (displayName === 'TodayMarker') {\n configs.push(getTodayMarkerConfig(child.props as { color?: string; width?: number; label?: string }))\n } else if (displayName === 'CustomMarker') {\n configs.push(getCustomMarkerConfig(child.props as { date: number; color?: string; width?: number; label?: string }))\n }\n })\n return configs\n }, [children])\n const markersKey = useMemo(() => markerConfigs.map(m => `${m.date}|${m.color}|${m.width}|${m.label ?? ''}`).join(';'), [markerConfigs])\n const markersRef = useRef(markerConfigs)\n markersRef.current = markerConfigs\n\n // TodayMarker auto-update: refresh overlay on interval\n const todayMarkerInterval = useMemo(() => {\n let interval = 0\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return\n const displayName = (child.type as { displayName?: string })?.displayName\n if (displayName === 'TodayMarker') {\n interval = getTodayMarkerInterval(child.props as { interval?: number })\n }\n })\n return interval\n }, [children])\n\n // --- PROPS REF ---\n const propsRef = useRef({\n groups, items, intervalTree, layoutEngine, itemRenderer, groupRenderer,\n theme, selected, dependencies, dayStyle, rowStyle, showCursorLine,\n canvasWidth, canvasHeight, lineHeight, itemHeightRatio,\n onTimeChange, onZoom, onItemHover, onItemClick, onItemDoubleClick,\n onItemContextMenu, onItemMove, onItemResize, onCanvasDoubleClick, onCanvasContextMenu,\n canMove, canResize, canChangeGroup, dragSnap, sidebarWidth, moveResizeValidator,\n })\n propsRef.current = {\n groups, items, intervalTree, layoutEngine, itemRenderer, groupRenderer,\n theme, selected, dependencies, dayStyle, rowStyle, showCursorLine,\n canvasWidth, canvasHeight, lineHeight, itemHeightRatio,\n onTimeChange, onZoom, onItemHover, onItemClick, onItemDoubleClick,\n onItemContextMenu, onItemMove, onItemResize, onCanvasDoubleClick, onCanvasContextMenu,\n canMove, canResize, canChangeGroup, dragSnap, sidebarWidth, moveResizeValidator,\n }\n\n // --- DRAW FUNCTIONS ---\n const drawGrid = useCallback(() => {\n const canvas = gridCanvasRef.current\n if (!canvas) return\n const p = propsRef.current\n const ctx = setupCanvas(canvas, p.canvasWidth, p.canvasHeight)\n clearCanvas(ctx, canvas)\n gridLayer.draw(ctx, viewStateRef.current, p.groups, p.theme, p.dayStyle, p.rowStyle)\n }, [gridLayer])\n\n const drawItems = useCallback(() => {\n const canvas = itemsCanvasRef.current\n if (!canvas) return\n const p = propsRef.current\n const ctx = setupCanvas(canvas, p.canvasWidth, p.canvasHeight)\n clearCanvas(ctx, canvas)\n itemsLayer.draw(\n ctx, viewStateRef.current, p.groups, p.items, p.intervalTree, p.layoutEngine,\n p.itemRenderer, p.groupRenderer, p.theme, p.selected, hoveredItemIdRef.current, p.dependencies,\n )\n }, [itemsLayer])\n\n const calculateSnapX = useCallback((item: (typeof items)[0], deltaX: number) => {\n const vs = viewStateRef.current\n const p = propsRef.current\n const pixelsPerMs = p.canvasWidth / (vs.visibleTimeEnd - vs.visibleTimeStart)\n const deltaMs = deltaX / pixelsPerMs\n const newStart = item.start_time + deltaMs\n const snapped = Math.round(newStart / p.dragSnap) * p.dragSnap\n return vs.timeToX(snapped)\n }, [])\n\n const drawOverlay = useCallback(() => {\n const canvas = overlayCanvasRef.current\n if (!canvas) return\n const p = propsRef.current\n const ctx = setupCanvas(canvas, p.canvasWidth, p.canvasHeight)\n clearCanvas(ctx, canvas)\n\n const vs = viewStateRef.current\n const state = interactionHandler.getState()\n let interactionRender = null\n if (state) {\n const origX = vs.timeToX(state.item.start_time)\n const origWidth = vs.timeToX(state.item.end_time) - origX\n let x: number, width: number\n if (state.mode === 'resize-left') {\n x = origX + state.deltaX\n width = origWidth - state.deltaX\n } else if (state.mode === 'resize-right') {\n x = origX\n width = origWidth + state.deltaX\n } else {\n // move\n x = origX + state.deltaX\n width = origWidth\n }\n const groupIndex = getGroupIndex(state.currentGroup, p.groups)\n const targetGroupY = vs.groupIndexToY(groupIndex)\n const groupChanged = state.currentGroup !== state.originalGroup\n interactionRender = {\n item: state.item,\n mode: state.mode,\n bounds: { x, y: targetGroupY + (p.lineHeight - p.lineHeight * p.itemHeightRatio) / 2, width, height: p.lineHeight * p.itemHeightRatio },\n renderer: p.itemRenderer,\n targetGroupY,\n groupChanged,\n }\n }\n\n overlayLayer.draw(ctx, vs, p.theme, {\n cursorX: p.showCursorLine ? cursorXRef.current : null,\n snapX: state ? calculateSnapX(state.item, state.deltaX) : null,\n markers: markersRef.current,\n interaction: interactionRender,\n })\n }, [overlayLayer, interactionHandler, calculateSnapX, getGroupIndex])\n\n // --- RENDER SCHEDULER ---\n const schedulerRef = useRef<RenderScheduler | null>(null)\n if (!schedulerRef.current) {\n schedulerRef.current = new RenderScheduler((flags) => {\n if (flags.grid) drawGrid()\n if (flags.items) drawItems()\n if (flags.overlay) drawOverlay()\n })\n }\n const scheduler = schedulerRef.current\n\n useEffect(() => {\n return () => scheduler.dispose()\n }, [scheduler])\n\n // --- TODAY MARKER AUTO-UPDATE ---\n useEffect(() => {\n if (!todayMarkerInterval) return\n const timer = setInterval(() => {\n const configs: MarkerConfig[] = []\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return\n const displayName = (child.type as { displayName?: string })?.displayName\n if (displayName === 'TodayMarker') {\n configs.push(getTodayMarkerConfig(child.props as { color?: string; width?: number; label?: string }))\n } else if (displayName === 'CustomMarker') {\n configs.push(getCustomMarkerConfig(child.props as { date: number; color?: string; width?: number; label?: string }))\n }\n })\n markersRef.current = configs\n scheduler.markDirty('overlay')\n }, todayMarkerInterval)\n return () => clearInterval(timer)\n }, [todayMarkerInterval, children, scheduler])\n\n // --- SYNC ON DIMENSION/DATA CHANGES ---\n useEffect(() => {\n viewStateRef.current.update({ canvasWidth, canvasHeight, sidebarWidth, lineHeight, groupCount: groups.length })\n scheduler.markAllDirty()\n }, [canvasWidth, canvasHeight, sidebarWidth, lineHeight, groups.length, scheduler])\n\n useEffect(() => {\n scheduler.markDirty('grid')\n scheduler.markDirty('items')\n }, [items, groups, selected, theme, dayStyle, rowStyle, intervalTree, layoutEngine, scheduler])\n\n const prevMarkersKey = useRef(markersKey)\n useEffect(() => {\n if (markersKey !== prevMarkersKey.current) {\n prevMarkersKey.current = markersKey\n scheduler.markDirty('overlay')\n }\n }, [markersKey, scheduler])\n\n // --- CONTROLLED MODE ---\n const prevControlledStart = useRef(props.visibleTimeStart)\n const prevControlledEnd = useRef(props.visibleTimeEnd)\n if (props.visibleTimeStart !== undefined && props.visibleTimeStart !== prevControlledStart.current) {\n prevControlledStart.current = props.visibleTimeStart\n viewStateRef.current.update({ visibleTimeStart: props.visibleTimeStart })\n scheduler.markAllDirty()\n }\n if (props.visibleTimeEnd !== undefined && props.visibleTimeEnd !== prevControlledEnd.current) {\n prevControlledEnd.current = props.visibleTimeEnd\n viewStateRef.current.update({ visibleTimeEnd: props.visibleTimeEnd })\n scheduler.markAllDirty()\n }\n\n // --- THROTTLED PARENT CALLBACKS ---\n const callbackTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const scheduleCallbacks = useCallback((type: 'zoom' | 'scroll') => {\n if (callbackTimerRef.current !== null) return\n callbackTimerRef.current = setTimeout(() => {\n callbackTimerRef.current = null\n const vs = viewStateRef.current\n const p = propsRef.current\n if (type === 'zoom') {\n p.onZoom?.(vs.visibleTimeStart, vs.visibleTimeEnd)\n } else {\n p.onTimeChange?.(vs.visibleTimeStart, vs.visibleTimeEnd)\n }\n }, HEADER_THROTTLE_MS)\n }, [])\n\n useEffect(() => {\n return () => { if (callbackTimerRef.current !== null) clearTimeout(callbackTimerRef.current) }\n }, [])\n\n // --- ZOOM HANDLER ---\n const zoomHandlerRef = useRef<ZoomHandler | null>(null)\n const zoomHandler = useMemo(() => {\n return new ZoomHandler(\n (newStart, newEnd) => {\n viewStateRef.current.update({ visibleTimeStart: newStart, visibleTimeEnd: newEnd })\n zoomHandlerRef.current?.updateBounds(newStart, newEnd)\n scheduler.markAllDirty()\n scheduleHeaderSync()\n scheduleCallbacks('zoom')\n },\n defaultTimeStart,\n defaultTimeEnd,\n minZoom,\n maxZoom,\n )\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n zoomHandlerRef.current = zoomHandler\n\n // --- WHEEL HANDLER ---\n const handleVerticalScroll = useCallback((deltaY: number) => {\n const vs = viewStateRef.current\n const totalHeight = vs.groupCount * vs.lineHeight\n const maxScroll = Math.max(0, totalHeight - vs.canvasHeight)\n const newScrollTop = Math.max(0, Math.min(maxScroll, vs.scrollTop + deltaY))\n if (newScrollTop === vs.scrollTop) return\n vs.update({ scrollTop: newScrollTop })\n scheduler.markDirty('grid')\n scheduler.markDirty('items')\n scheduler.markDirty('overlay')\n setSidebarScrollTop(newScrollTop)\n }, [scheduler])\n\n const handleHorizontalScroll = useCallback((deltaX: number) => {\n const vs = viewStateRef.current\n const pixelsPerMs = vs.canvasWidth / (vs.visibleTimeEnd - vs.visibleTimeStart)\n const deltaMs = deltaX / pixelsPerMs\n const newStart = vs.visibleTimeStart + deltaMs\n const newEnd = vs.visibleTimeEnd + deltaMs\n vs.update({ visibleTimeStart: newStart, visibleTimeEnd: newEnd })\n zoomHandlerRef.current?.updateBounds(newStart, newEnd)\n scheduler.markAllDirty()\n flushSync(() => syncHeaderState())\n propsRef.current.onTimeChange?.(newStart, newEnd)\n }, [scheduler, syncHeaderState])\n\n useEffect(() => {\n const el = interactionRef.current\n if (!el) return\n const handleWheel = (e: WheelEvent) => {\n if (e.ctrlKey || e.metaKey || e.altKey) {\n e.preventDefault()\n const rect = el.getBoundingClientRect()\n const cursorRatio = (e.clientX - rect.left) / rect.width\n zoomHandler.handleWheelZoom(e, cursorRatio)\n } else if (e.shiftKey) {\n e.preventDefault()\n handleHorizontalScroll(e.deltaY)\n } else {\n const deltaX = e.deltaX\n if (deltaX !== 0 && Math.abs(deltaX) > Math.abs(e.deltaY)) {\n e.preventDefault()\n handleHorizontalScroll(deltaX)\n } else if (e.deltaY !== 0) {\n handleVerticalScroll(e.deltaY)\n }\n }\n }\n el.addEventListener('wheel', handleWheel, { passive: false })\n return () => el.removeEventListener('wheel', handleWheel)\n }, [zoomHandler, handleVerticalScroll, handleHorizontalScroll])\n\n // --- TOUCH PINCH-TO-ZOOM ---\n const touchRef = useRef<{ lastDistance: number | null; lastCenter: number | null }>({ lastDistance: null, lastCenter: null })\n\n useEffect(() => {\n const el = interactionRef.current\n if (!el) return\n\n const getDistance = (t1: Touch, t2: Touch) => Math.abs(t1.clientX - t2.clientX)\n const getCenter = (t1: Touch, t2: Touch, rect: DOMRect) => ((t1.clientX + t2.clientX) / 2) - rect.left\n\n const handleTouchStart = (e: TouchEvent) => {\n if (e.touches.length === 2) {\n e.preventDefault()\n touchRef.current.lastDistance = getDistance(e.touches[0], e.touches[1])\n touchRef.current.lastCenter = null\n }\n }\n\n const handleTouchMove = (e: TouchEvent) => {\n if (e.touches.length === 2 && touchRef.current.lastDistance !== null) {\n e.preventDefault()\n const newDistance = getDistance(e.touches[0], e.touches[1])\n const rect = el.getBoundingClientRect()\n const center = getCenter(e.touches[0], e.touches[1], rect)\n const cursorRatio = center / rect.width\n\n if (newDistance !== 0 && touchRef.current.lastDistance !== 0) {\n const scale = touchRef.current.lastDistance / newDistance\n const vs = viewStateRef.current\n const currentDuration = vs.visibleTimeEnd - vs.visibleTimeStart\n let newDuration = currentDuration * scale\n newDuration = Math.max(minZoom, Math.min(maxZoom, newDuration))\n\n const cursorTime = vs.visibleTimeStart + currentDuration * cursorRatio\n const newStart = cursorTime - newDuration * cursorRatio\n const newEnd = cursorTime + newDuration * (1 - cursorRatio)\n\n vs.update({ visibleTimeStart: newStart, visibleTimeEnd: newEnd })\n zoomHandlerRef.current?.updateBounds(newStart, newEnd)\n scheduler.markAllDirty()\n scheduleHeaderSync()\n scheduleCallbacks('zoom')\n }\n touchRef.current.lastDistance = newDistance\n }\n }\n\n const handleTouchEnd = () => {\n touchRef.current.lastDistance = null\n touchRef.current.lastCenter = null\n }\n\n el.addEventListener('touchstart', handleTouchStart, { passive: false })\n el.addEventListener('touchmove', handleTouchMove, { passive: false })\n el.addEventListener('touchend', handleTouchEnd)\n return () => {\n el.removeEventListener('touchstart', handleTouchStart)\n el.removeEventListener('touchmove', handleTouchMove)\n el.removeEventListener('touchend', handleTouchEnd)\n }\n }, [scheduler, scheduleHeaderSync, scheduleCallbacks])\n\n // --- POINTER HANDLERS ---\n const handlePointerMove = useCallback((e: React.PointerEvent) => {\n const el = e.currentTarget as HTMLElement\n const rect = el.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n cursorXRef.current = x\n\n if (interactionHandler.isPending()) {\n interactionHandler.update(x, y)\n if (interactionHandler.isActive()) {\n const state = interactionHandler.getState()\n if (state && state.mode === 'move' && propsRef.current.canChangeGroup) {\n const group = hitTestGroup(y, viewStateRef.current, propsRef.current.groups)\n if (group) interactionHandler.setCurrentGroup(group.id)\n }\n scheduler.markDirty('overlay')\n }\n return\n }\n\n if (propsRef.current.showCursorLine) scheduler.markDirty('overlay')\n\n const p = propsRef.current\n const item = hitTest(x, y, viewStateRef.current, p.intervalTree, p.layoutEngine, p.groups)\n const newHoveredId = item?.id\n if (newHoveredId !== hoveredItemIdRef.current) {\n hoveredItemIdRef.current = newHoveredId\n scheduler.markDirty('items')\n p.onItemHover?.(newHoveredId ?? null, e.nativeEvent as unknown as PointerEvent)\n }\n\n // Cursor management\n if (item) {\n const edge = detectEdge(x, item, viewStateRef.current)\n const cr = p.canResize\n if (edge === 'left' && (cr === 'left' || cr === 'both')) {\n el.style.cursor = 'col-resize'\n } else if (edge === 'right' && (cr === 'right' || cr === 'both')) {\n el.style.cursor = 'col-resize'\n } else if (p.canMove) {\n el.style.cursor = 'grab'\n } else {\n el.style.cursor = 'default'\n }\n } else {\n el.style.cursor = 'default'\n }\n }, [interactionHandler, scheduler])\n\n const handlePointerDown = useCallback((e: React.PointerEvent) => {\n const p = propsRef.current\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const item = hitTest(x, y, viewStateRef.current, p.intervalTree, p.layoutEngine, p.groups)\n if (!item) return\n\n const edge = detectEdge(x, item, viewStateRef.current)\n const cr = p.canResize\n\n if (edge === 'left' && (cr === 'left' || cr === 'both')) {\n interactionHandler.startInteraction(item, 'resize-left', x, y)\n } else if (edge === 'right' && (cr === 'right' || cr === 'both')) {\n interactionHandler.startInteraction(item, 'resize-right', x, y)\n } else if (p.canMove) {\n interactionHandler.startInteraction(item, 'move', x, y)\n }\n }, [interactionHandler])\n\n const handlePointerUp = useCallback((e: React.PointerEvent) => {\n const el = e.currentTarget as HTMLElement\n if (interactionHandler.isActive()) {\n const state = interactionHandler.getState()\n const vs = viewStateRef.current\n const pixelsPerMs = vs.canvasWidth / (vs.visibleTimeEnd - vs.visibleTimeStart)\n if (state) {\n const validator = propsRef.current.moveResizeValidator\n if (state.mode === 'move') {\n const result = interactionHandler.endMove(pixelsPerMs)\n if (result) {\n const validatedTime = validator ? validator('move', state.item.id, result.newStartTime) : result.newStartTime\n propsRef.current.onItemMove?.(state.item.id, validatedTime, result.newGroupId)\n }\n } else {\n const result = interactionHandler.endResize(pixelsPerMs)\n if (result) {\n const validatedTime = validator ? validator('resize', state.item.id, result.newTime, result.edge) : result.newTime\n propsRef.current.onItemResize?.(state.item.id, validatedTime, result.edge)\n }\n }\n }\n el.style.cursor = 'default'\n scheduler.markDirty('overlay')\n return\n }\n if (interactionHandler.isPending()) interactionHandler.cancel()\n const rect = el.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const item = hitTest(x, y, viewStateRef.current, propsRef.current.intervalTree, propsRef.current.layoutEngine, propsRef.current.groups)\n if (item) propsRef.current.onItemClick?.(item.id, e.nativeEvent as unknown as PointerEvent)\n }, [interactionHandler, scheduler])\n\n const handleDoubleClick = useCallback((e: React.MouseEvent) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const p = propsRef.current\n const item = hitTest(x, y, viewStateRef.current, p.intervalTree, p.layoutEngine, p.groups)\n if (item) {\n p.onItemDoubleClick?.(item.id, e.nativeEvent as unknown as PointerEvent)\n } else {\n const group = hitTestGroup(y, viewStateRef.current, p.groups)\n const time = viewStateRef.current.xToTime(x)\n if (group) p.onCanvasDoubleClick?.(group.id as number, time)\n }\n }, [])\n\n const handleContextMenu = useCallback((e: React.MouseEvent) => {\n e.preventDefault()\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n const p = propsRef.current\n const item = hitTest(x, y, viewStateRef.current, p.intervalTree, p.layoutEngine, p.groups)\n if (item) {\n p.onItemContextMenu?.(item.id, e.nativeEvent as unknown as PointerEvent)\n } else {\n const group = hitTestGroup(y, viewStateRef.current, p.groups)\n const time = viewStateRef.current.xToTime(x)\n if (group) p.onCanvasContextMenu?.(group.id as number, time, e.nativeEvent as unknown as PointerEvent)\n }\n }, [])\n\n const handlePointerLeave = useCallback(() => {\n cursorXRef.current = null\n if (interactionRef.current) interactionRef.current.style.cursor = 'default'\n if (hoveredItemIdRef.current !== undefined) {\n hoveredItemIdRef.current = undefined\n scheduler.markDirty('items')\n propsRef.current.onItemHover?.(null, new PointerEvent('pointerleave'))\n }\n if (propsRef.current.showCursorLine) scheduler.markDirty('overlay')\n }, [scheduler])\n\n // --- HEADER CHILDREN ---\n const headerChildren = useMemo(() => {\n const headers: React.ReactNode[] = []\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return\n const displayName = (child.type as { displayName?: string })?.displayName\n if (displayName === 'TimelineHeaders') {\n const childProps = child.props as Record<string, unknown>\n headers.push(\n React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n visibleTimeStart: childProps.visibleTimeStart ?? headerTimeStart,\n visibleTimeEnd: childProps.visibleTimeEnd ?? headerTimeEnd,\n canvasWidth: childProps.canvasWidth ?? canvasWidth,\n sidebarWidth: childProps.sidebarWidth ?? sidebarWidth,\n theme: childProps.theme ?? theme,\n onZoomToInterval: childProps.onZoomToInterval ?? ((start: number, end: number) => {\n viewStateRef.current.update({ visibleTimeStart: start, visibleTimeEnd: end })\n scheduler.markAllDirty()\n syncHeaderState()\n propsRef.current.onTimeChange?.(start, end)\n propsRef.current.onZoom?.(start, end)\n }),\n }),\n )\n }\n })\n return headers\n }, [children, headerTimeStart, headerTimeEnd, canvasWidth, sidebarWidth, theme, scheduler, syncHeaderState])\n\n // --- INITIAL DRAW ---\n const initialDrawDone = useRef(false)\n useEffect(() => {\n if (!initialDrawDone.current) {\n initialDrawDone.current = true\n scheduler.markAllDirty()\n }\n }, [scheduler])\n\n // --- IMPERATIVE HANDLE (print capture) ---\n useImperativeHandle(ref, () => ({\n captureToCanvas({ timeStart, timeEnd, scale, sidebarWidth: printSidebarWidth }) {\n const p = propsRef.current\n const headerRowHeight = 28\n const headerHeight = headerRowHeight * 3\n const totalHeight = p.groups.length * p.lineHeight\n\n // Preserve the current zoom level (pixels per ms) from the on-screen view\n const vs = viewStateRef.current\n const currentPixelsPerMs = p.canvasWidth / (vs.visibleTimeEnd - vs.visibleTimeStart)\n const printDuration = timeEnd - timeStart\n const timelineWidth = Math.max(p.canvasWidth, Math.round(printDuration * currentPixelsPerMs))\n\n const compositeWidth = (printSidebarWidth + timelineWidth) * scale\n const compositeHeight = (headerHeight + totalHeight) * scale\n\n const canvas = document.createElement('canvas')\n canvas.width = compositeWidth\n canvas.height = compositeHeight\n const ctx = canvas.getContext('2d')!\n ctx.scale(scale, scale)\n\n // --- Draw sidebar ---\n for (let i = 0; i < p.groups.length; i++) {\n const group = p.groups[i]\n const y = headerHeight + i * p.lineHeight\n\n // Row background from rowStyle\n if (p.rowStyle) {\n const style = p.rowStyle(group)\n if (style?.backgroundColor) {\n ctx.fillStyle = style.backgroundColor\n ctx.fillRect(0, y, printSidebarWidth, p.lineHeight)\n }\n }\n\n // Group title\n const groupType = group.type as string | undefined\n let fontWeight = '400'\n let indent = 8\n if (groupType === 'project') {\n fontWeight = '700'\n } else if (groupType === 'CAG') {\n fontWeight = '600'\n } else if (groupType === 'CA') {\n fontWeight = '400'\n indent = 24\n }\n\n ctx.fillStyle = '#111'\n ctx.font = `${fontWeight} 12px sans-serif`\n ctx.textBaseline = 'middle'\n ctx.fillText(group.title, indent, y + p.lineHeight / 2, printSidebarWidth - indent - 4)\n }\n\n // --- Draw headers ---\n const drawHeaderRow = (rowY: number, getLabel: (time: dayjs.Dayjs) => string, unit: dayjs.ManipulateType) => {\n ctx.fillStyle = p.theme.header?.bg ?? '#f5f5f5'\n ctx.fillRect(printSidebarWidth, rowY, timelineWidth, headerRowHeight)\n ctx.strokeStyle = p.theme.grid?.line ?? '#e0e0e0'\n ctx.lineWidth = 1\n ctx.strokeRect(printSidebarWidth, rowY, timelineWidth, headerRowHeight)\n\n let cursor = dayjs(timeStart).startOf(unit)\n if (cursor.valueOf() < timeStart) cursor = cursor.add(1, unit)\n\n const pxPerMs = timelineWidth / (timeEnd - timeStart)\n\n while (cursor.valueOf() < timeEnd) {\n const nextCursor = cursor.add(1, unit)\n const x = printSidebarWidth + (cursor.valueOf() - timeStart) * pxPerMs\n const endX = printSidebarWidth + (Math.min(nextCursor.valueOf(), timeEnd) - timeStart) * pxPerMs\n const width = endX - x\n\n // Vertical divider\n ctx.beginPath()\n ctx.moveTo(x, rowY)\n ctx.lineTo(x, rowY + headerRowHeight)\n ctx.stroke()\n\n // Label\n ctx.fillStyle = '#333'\n ctx.font = '600 11px sans-serif'\n ctx.textBaseline = 'middle'\n ctx.textAlign = 'center'\n ctx.fillText(getLabel(cursor), x + width / 2, rowY + headerRowHeight / 2, width - 4)\n\n cursor = nextCursor\n }\n ctx.textAlign = 'start' // reset\n }\n\n drawHeaderRow(0, (d) => d.format('YYYY'), 'year')\n drawHeaderRow(headerRowHeight, (d) => d.format('MM'), 'month')\n drawHeaderRow(headerRowHeight * 2, (d) => String(d.isoWeek()), 'week')\n\n // --- Draw timeline layers ---\n const printViewState = new ViewState({\n visibleTimeStart: timeStart,\n visibleTimeEnd: timeEnd,\n canvasWidth: timelineWidth,\n canvasHeight: totalHeight,\n sidebarWidth: 0,\n lineHeight: p.lineHeight,\n groupCount: p.groups.length,\n buffer: 1,\n scrollTop: 0,\n })\n\n // Offset context for timeline area\n ctx.save()\n ctx.translate(printSidebarWidth, headerHeight)\n\n // Clip to timeline area\n ctx.beginPath()\n ctx.rect(0, 0, timelineWidth, totalHeight)\n ctx.clip()\n\n gridLayer.draw(ctx, printViewState, p.groups, p.theme, p.dayStyle, p.rowStyle)\n itemsLayer.draw(\n ctx, printViewState, p.groups, p.items, p.intervalTree, p.layoutEngine,\n p.itemRenderer, p.groupRenderer, p.theme, p.selected, undefined, p.dependencies,\n )\n overlayLayer.draw(ctx, printViewState, p.theme, {\n cursorX: null,\n snapX: null,\n markers: markersRef.current,\n interaction: null,\n })\n\n ctx.restore()\n\n return canvas\n },\n }), [gridLayer, itemsLayer, overlayLayer])\n\n // --- ON READY CALLBACK ---\n useEffect(() => {\n const api: CanvasTimelineRef = {\n captureToCanvas({ timeStart, timeEnd, scale, sidebarWidth: printSidebarWidth }) {\n const p = propsRef.current\n const headerRowHeight = 28\n const headerHeight = headerRowHeight * 3\n const totalHeight = p.groups.length * p.lineHeight\n const vs = viewStateRef.current\n const currentPixelsPerMs = p.canvasWidth / (vs.visibleTimeEnd - vs.visibleTimeStart)\n const printDuration = timeEnd - timeStart\n const timelineWidth = Math.max(p.canvasWidth, Math.round(printDuration * currentPixelsPerMs))\n const fullWidth = printSidebarWidth + timelineWidth\n const fullHeight = headerHeight + totalHeight\n\n const canvas = document.createElement('canvas')\n canvas.width = fullWidth * scale\n canvas.height = fullHeight * scale\n const ctx = canvas.getContext('2d')!\n ctx.scale(scale, scale)\n ctx.fillStyle = '#FFFFFF'\n ctx.fillRect(0, 0, fullWidth, fullHeight)\n\n // Sidebar\n ctx.save()\n ctx.beginPath()\n ctx.rect(0, 0, printSidebarWidth, fullHeight)\n ctx.clip()\n ctx.fillStyle = '#F9FAFB'\n ctx.fillRect(0, 0, printSidebarWidth, headerHeight)\n ctx.strokeStyle = '#E5E7EB'\n ctx.lineWidth = 1\n ctx.strokeRect(0, 0, printSidebarWidth, headerHeight)\n for (let i = 0; i < p.groups.length; i++) {\n const group = p.groups[i]\n const y = headerHeight + i * p.lineHeight\n const rs = p.rowStyle?.(group)\n ctx.fillStyle = rs?.backgroundColor ?? (i % 2 === 0 ? '#FFFFFF' : '#F7F7F7')\n ctx.fillRect(0, y, printSidebarWidth, p.lineHeight)\n ctx.strokeStyle = '#E5E5E5'\n ctx.lineWidth = 0.5\n ctx.beginPath()\n ctx.moveTo(0, y + p.lineHeight)\n ctx.lineTo(printSidebarWidth, y + p.lineHeight)\n ctx.stroke()\n const gt = (group.type as string) ?? ''\n let indent = 8, fw = '400', fs = 11\n if (gt === 'project') { fw = '700'; fs = 12 }\n else if (gt === 'control_area_group') { fw = '600' }\n else if (gt === 'control_area') { indent = 24 }\n ctx.fillStyle = '#374151'\n ctx.font = `${fw} ${fs}px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif`\n ctx.textBaseline = 'middle'\n const title = typeof group.title === 'string' ? group.title : String(group.title)\n ctx.fillText(title, indent, y + p.lineHeight / 2, printSidebarWidth - indent - 8)\n }\n ctx.strokeStyle = '#E5E7EB'\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(printSidebarWidth, 0)\n ctx.lineTo(printSidebarWidth, fullHeight)\n ctx.stroke()\n ctx.restore()\n\n // Headers\n ctx.save()\n ctx.beginPath()\n ctx.rect(printSidebarWidth, 0, timelineWidth, headerHeight)\n ctx.clip()\n const duration = timeEnd - timeStart\n const units: Array<{ unit: 'year' | 'month' | 'week'; row: number }> = [\n { unit: 'year', row: 0 }, { unit: 'month', row: 1 }, { unit: 'week', row: 2 },\n ]\n for (const { unit, row } of units) {\n const hy = row * headerRowHeight\n ctx.fillStyle = '#F9FAFB'\n ctx.fillRect(printSidebarWidth, hy, timelineWidth, headerRowHeight)\n let cur = dayjs(timeStart).startOf(unit)\n const endBound = dayjs(timeEnd).add(1, unit)\n while (cur.isBefore(endBound)) {\n const next = cur.add(1, unit)\n const sx = printSidebarWidth + ((cur.valueOf() - timeStart) / duration) * timelineWidth\n const w = ((next.valueOf() - cur.valueOf()) / duration) * timelineWidth\n ctx.strokeStyle = '#E5E7EB'\n ctx.lineWidth = 0.5\n ctx.strokeRect(sx, hy, w, headerRowHeight)\n let label: string\n if (unit === 'year') label = cur.format('YYYY')\n else if (unit === 'month') label = cur.format('MM')\n else label = `${cur.week()}`\n ctx.fillStyle = '#6c737f'\n ctx.font = unit === 'year'\n ? '600 11px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif'\n : '400 11px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif'\n ctx.textBaseline = 'middle'\n ctx.textAlign = 'center'\n if (w > 20) ctx.fillText(label, sx + w / 2, hy + headerRowHeight / 2)\n cur = next\n }\n }\n ctx.textAlign = 'start'\n ctx.restore()\n\n // Timeline\n ctx.save()\n ctx.beginPath()\n ctx.rect(printSidebarWidth, headerHeight, timelineWidth, totalHeight)\n ctx.clip()\n ctx.translate(printSidebarWidth, headerHeight)\n const pv = new ViewState({\n visibleTimeStart: timeStart, visibleTimeEnd: timeEnd,\n canvasWidth: timelineWidth, canvasHeight: totalHeight,\n sidebarWidth: 0, lineHeight: p.lineHeight,\n groupCount: p.groups.length, buffer: 1, scrollTop: 0,\n })\n gridLayer.draw(ctx, pv, p.groups, p.theme, p.dayStyle, p.rowStyle)\n itemsLayer.draw(ctx, pv, p.groups, p.items, p.intervalTree, p.layoutEngine,\n p.itemRenderer, p.groupRenderer, p.theme, p.selected, undefined, p.dependencies)\n overlayLayer.draw(ctx, pv, p.theme, { cursorX: null, markers: markersRef.current })\n ctx.restore()\n\n return canvas\n },\n }\n onReady?.(api)\n }, [onReady, gridLayer, itemsLayer, overlayLayer])\n\n // --- RENDER ---\n const canvasContainerStyle: React.CSSProperties = {\n position: 'relative',\n width: canvasWidth,\n height: canvasHeight,\n overflow: 'hidden',\n cursor: 'default',\n }\n\n const canvasStyle: React.CSSProperties = { position: 'absolute', top: 0, left: 0 }\n\n return (\n <div ref={outerRef} style={{ display: 'flex', flexDirection: 'column', width: '100%' }}>\n {headerChildren}\n <div ref={containerRef} style={{ display: 'flex', overflow: 'hidden' }}>\n <Sidebar\n groups={groups}\n width={sidebarWidth}\n lineHeight={lineHeight}\n scrollTop={sidebarScrollTop}\n canvasHeight={canvasHeight}\n theme={theme}\n groupRenderer={sidebarGroupRenderer}\n onScroll={(newScrollTop) => {\n viewStateRef.current.update({ scrollTop: newScrollTop })\n scheduler.markDirty('grid')\n scheduler.markDirty('items')\n scheduler.markDirty('overlay')\n setSidebarScrollTop(newScrollTop)\n }}\n />\n <div\n ref={interactionRef}\n style={canvasContainerStyle}\n onPointerMove={handlePointerMove}\n onPointerDown={handlePointerDown}\n onPointerUp={handlePointerUp}\n onDoubleClick={handleDoubleClick}\n onContextMenu={handleContextMenu}\n onPointerLeave={handlePointerLeave}\n >\n <canvas ref={gridCanvasRef} style={{ ...canvasStyle, zIndex: 0 }} />\n <canvas ref={itemsCanvasRef} style={{ ...canvasStyle, zIndex: 1 }} />\n <canvas ref={overlayCanvasRef} style={{ ...canvasStyle, zIndex: 2 }} />\n </div>\n {rightSidebarWidth && rightSidebarGroupRenderer ? (\n <Sidebar\n groups={groups}\n width={rightSidebarWidth}\n lineHeight={lineHeight}\n scrollTop={sidebarScrollTop}\n canvasHeight={canvasHeight}\n theme={theme}\n groupRenderer={rightSidebarGroupRenderer}\n onScroll={(newScrollTop) => {\n viewStateRef.current.update({ scrollTop: newScrollTop })\n scheduler.markDirty('grid')\n scheduler.markDirty('items')\n scheduler.markDirty('overlay')\n setSidebarScrollTop(newScrollTop)\n }}\n />\n ) : null}\n </div>\n </div>\n )\n}))\n","import React from 'react'\nimport type { TimelineTheme } from '../types'\n\nexport interface TimelineHeadersProps {\n children: React.ReactNode\n theme?: TimelineTheme\n className?: string\n classNames?: string\n style?: React.CSSProperties\n visibleTimeStart?: number\n visibleTimeEnd?: number\n canvasWidth?: number\n sidebarWidth?: number\n onZoomToInterval?: (start: number, end: number) => void\n}\n\nexport function TimelineHeaders({ children, theme, className, classNames: _classNames, style, visibleTimeStart, visibleTimeEnd, canvasWidth, sidebarWidth = 0, onZoomToInterval }: TimelineHeadersProps) {\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child\n const displayName = (child.type as { displayName?: string })?.displayName\n if (displayName === 'DateHeader') {\n const childProps = child.props as Record<string, unknown>\n const enhanced = React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n visibleTimeStart: childProps.visibleTimeStart ?? visibleTimeStart,\n visibleTimeEnd: childProps.visibleTimeEnd ?? visibleTimeEnd,\n canvasWidth: childProps.canvasWidth ?? canvasWidth,\n theme: childProps.theme ?? theme,\n onZoomToInterval: childProps.onIntervalClick ?? childProps.onZoomToInterval ?? onZoomToInterval,\n })\n return (\n <div style={{ display: 'flex' }}>\n <div style={{ width: sidebarWidth, flexShrink: 0 }} />\n <div style={{ flex: 1, overflow: 'hidden' }}>{enhanced}</div>\n </div>\n )\n }\n return child\n })\n\n return (\n <div className={className} style={{\n position: 'sticky', top: 0, zIndex: 20, display: 'flex', flexDirection: 'column',\n backgroundColor: theme?.header.bg ?? '#F9FAFB',\n borderTop: `1px solid ${theme?.header.border ?? '#E5E7EB'}`,\n borderBottom: `1px solid ${theme?.header.border ?? '#E5E7EB'}`,\n ...style,\n }}>\n {enhancedChildren}\n </div>\n )\n}\nTimelineHeaders.displayName = 'TimelineHeaders'\n","!function(e,t){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=t():\"function\"==typeof define&&define.amd?define(t):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_plugin_weekOfYear=t()}(this,(function(){\"use strict\";var e=\"week\",t=\"year\";return function(i,n,r){var f=n.prototype;f.week=function(i){if(void 0===i&&(i=null),null!==i)return this.add(7*(i-this.week()),\"day\");var n=this.$locale().yearStart||1;if(11===this.month()&&this.date()>25){var f=r(this).startOf(t).add(1,t).date(n),s=r(this).endOf(e);if(f.isBefore(s))return 1}var a=r(this).startOf(t).date(n).startOf(e).subtract(1,\"millisecond\"),o=this.diff(a,e,!0);return o<0?r(this).startOf(\"week\").week():Math.ceil(o)},f.weeks=function(e){return void 0===e&&(e=null),this.week(e)}}}));","import { useMemo, useCallback } from 'react'\nimport dayjs from 'dayjs'\nimport weekOfYear from 'dayjs/plugin/weekOfYear'\nimport type { TimelineTheme } from '../types'\n\ndayjs.extend(weekOfYear)\n\nexport type DateUnit = 'year' | 'month' | 'week' | 'day' | 'hour'\n\n// Minimum cell width in pixels before the header auto-hides\nconst DEFAULT_MIN_CELL_WIDTH: Record<DateUnit, number> = {\n year: 30,\n month: 30,\n week: 20,\n day: 15,\n hour: 30,\n}\n\nexport interface DateHeaderProps {\n unit: DateUnit\n visibleTimeStart?: number\n visibleTimeEnd?: number\n canvasWidth?: number\n theme?: TimelineTheme\n height?: number\n className?: string\n labelFormat?: string | ((start: Date, end: Date, unit: DateUnit) => string)\n onIntervalClick?: (startTime: number, endTime: number) => void\n /** Minimum cell width in pixels. Header auto-hides when cells are narrower. Set to 0 to disable. */\n minCellWidth?: number\n // Called by TimelineHeaders to inject zoom behavior\n onZoomToInterval?: (start: number, end: number) => void\n}\n\nexport function DateHeader({\n unit,\n visibleTimeStart = 0,\n visibleTimeEnd = 0,\n canvasWidth = 0,\n theme,\n height = 28,\n className,\n labelFormat,\n onIntervalClick,\n minCellWidth,\n onZoomToInterval,\n}: DateHeaderProps) {\n const intervals = useMemo(() => {\n if (!visibleTimeStart || !visibleTimeEnd || !canvasWidth) return []\n\n const duration = visibleTimeEnd - visibleTimeStart\n\n // Check average cell width — auto-hide if too narrow\n const minWidth = minCellWidth ?? DEFAULT_MIN_CELL_WIDTH[unit]\n if (minWidth > 0) {\n const sampleStart = dayjs(visibleTimeStart).startOf(unit)\n const sampleEnd = sampleStart.add(1, unit)\n const avgCellWidth = ((sampleEnd.valueOf() - sampleStart.valueOf()) / duration) * canvasWidth\n if (avgCellWidth < minWidth) return []\n }\n\n const result: Array<{ start: number; end: number; label: string; left: number; width: number }> = []\n // Add buffer: 1 extra unit before and after visible range\n let current = dayjs(visibleTimeStart).startOf(unit).subtract(1, unit)\n const endBound = dayjs(visibleTimeEnd).add(2, unit).valueOf()\n\n while (current.valueOf() < endBound) {\n const next = current.add(1, unit)\n const start = current.valueOf()\n const end = next.valueOf()\n const left = ((start - visibleTimeStart) / duration) * canvasWidth\n const width = ((end - start) / duration) * canvasWidth\n const label = formatLabel(current, next, unit, labelFormat, width)\n result.push({ start, end, label, left, width })\n current = next\n }\n return result\n }, [visibleTimeStart, visibleTimeEnd, canvasWidth, unit, labelFormat, minCellWidth])\n\n const handleClick = useCallback((start: number, end: number) => {\n if (onIntervalClick) {\n onIntervalClick(start, end)\n } else if (onZoomToInterval) {\n onZoomToInterval(start, end)\n }\n }, [onIntervalClick, onZoomToInterval])\n\n // Auto-hide: return nothing if no intervals (cells too narrow)\n if (intervals.length === 0) return null\n\n return (\n <div style={{ display: 'flex', position: 'relative', height, overflow: 'hidden' }}>\n {intervals.map((interval) => (\n <div\n key={interval.start}\n className={className}\n onClick={() => handleClick(interval.start, interval.end)}\n style={{\n position: 'absolute',\n left: interval.left,\n width: interval.width,\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderRight: `1px solid ${theme?.header.border ?? '#E5E7EB'}`,\n borderBottom: `1px solid ${theme?.header.border ?? '#E5E7EB'}`,\n fontSize: 12,\n color: theme?.header.text ?? '#6c737f',\n backgroundColor: theme?.header.bg ?? '#F9FAFB',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n userSelect: 'none',\n padding: '0 4px',\n boxSizing: 'border-box',\n }}\n >\n <span>{interval.label}</span>\n </div>\n ))}\n </div>\n )\n}\nDateHeader.displayName = 'DateHeader'\n\nfunction formatLabel(\n start: dayjs.Dayjs,\n end: dayjs.Dayjs,\n unit: DateUnit,\n labelFormat: string | ((start: Date, end: Date, unit: DateUnit) => string) | undefined,\n _width: number,\n): string {\n if (typeof labelFormat === 'function') {\n return labelFormat(start.toDate(), end.toDate(), unit)\n }\n if (typeof labelFormat === 'string') {\n return start.format(labelFormat)\n }\n return formatDefault(start, unit)\n}\n\nfunction formatDefault(d: dayjs.Dayjs, unit: DateUnit): string {\n switch (unit) {\n case 'year': return d.format('YYYY')\n case 'month': return d.format('MM')\n case 'week': return `${d.week()}`\n case 'day': return d.format('D')\n case 'hour': return d.format('HH:mm')\n }\n}\n","import React from 'react'\n\ninterface SidebarHeaderProps {\n width: number\n children?: (props: { getRootProps: () => React.HTMLAttributes<HTMLDivElement> }) => React.ReactNode\n style?: React.CSSProperties\n}\n\nexport function SidebarHeader({ width, children, style }: SidebarHeaderProps) {\n const getRootProps = (): React.HTMLAttributes<HTMLDivElement> => ({ style: { width, ...style } })\n if (children) return <>{children({ getRootProps })}</>\n return <div style={{ width }} />\n}\nSidebarHeader.displayName = 'SidebarHeader'\n","import React from 'react'\ninterface CustomHeaderProps { children: React.ReactNode }\nexport function CustomHeader({ children }: CustomHeaderProps) { return <>{children}</> }\nCustomHeader.displayName = 'CustomHeader'\n"],"names":["DEFAULT_THEME","ViewState","config","params","time","x","y","raw","index","extend","firstVisible","visibleCount","lastVisible","scrollXOffset","bufferPixels","IntervalTree","items","getStart","getEnd","intervals","item","min","max","iv","center","leftIntervals","rightIntervals","overlapping","start","end","results","node","LayoutEngine","lineHeight","itemHeightRatio","stackItems","itemHeight","byGroup","arr","groupId","groupItems","a","b","d","levelEnds","maxLevel","level","i","itemId","hitTest","canvasX","canvasY","view","tree","layout","groups","groupIndexMap","candidates","topItem","topY","groupIndex","itemLayout","width","height","hitTestGroup","detectEdge","threshold","leftX","rightX","setupCanvas","canvas","dpr","targetW","targetH","ctx","clearCanvas","RenderScheduler","drawCallback","layer","flags","GridLayer","theme","dayStyle","rowStyle","group","bgColor","customRow","visibleStart","visibleEnd","dayPixelWidth","stepUnit","current","dayjs","batchColor","batchOpacity","batchStartX","customBorderLines","flushBatch","endX","date","custom","color","opacity","dow","line","ITEM_FONT","createDrawHelpers","bounds","w","h","radius","text","maxWidth","lo","hi","mid","candidate","color1","color2","grad","type","size","half","cx","cy","fillColor","stemW","stemX","textWidth","paddingH","pillHeight","pillWidth","ItemsLayer","_items","itemRenderer","groupRenderer","selected","hoveredItemId","dependencies","padding","queryStart","queryEnd","visibleItems","selectedSet","itemBoundsMap","yMin","yMax","state","helpers","boundsMap","dep","fromBounds","toBounds","isHighlighted","startX","startY","endY","dx","cpOffset","arrowSize","OverlayLayer","options","cursorX","snapX","markers","interaction","marker","maxBadgeWidth","badgeWidth","badgeHeight","badgeX","badgeY","maxTextWidth","displayText","MAX_DELTA","normalizeDelta","e","delta","ZoomHandler","onZoom","visibleTimeStart","visibleTimeEnd","minZoom","maxZoom","cursorRatio","speed","scale","currentDuration","newDuration","newStart","newEnd","ACTIVATION_THRESHOLD","InteractionHandler","dragSnap","mode","pixelsPerMs","deltaMs","newStartTime","snapped","newGroupId","edge","newTime","_a","t","module","this","s","n","o","r","u","OVERSCAN","Sidebar","scrollTop","canvasHeight","onScroll","containerRef","useRef","isScrollingRef","totalHeight","displayHeight","handleScroll","useCallback","useEffect","visibleGroups","_jsx","TodayMarker","_props","getTodayMarkerConfig","props","getTodayMarkerInterval","CustomMarker","getCustomMarkerConfig","isoWeek","mergeTheme","partial","HEADER_THROTTLE_MS","CanvasTimeline","React","forwardRef","ref","defaultTimeStart","defaultTimeEnd","sidebarWidth","canMove","canChangeGroup","canResize","themePartial","showCursorLine","sidebarGroupRenderer","onItemClick","onItemDoubleClick","onItemContextMenu","onItemMove","onItemResize","moveResizeValidator","onItemHover","onCanvasDoubleClick","onCanvasContextMenu","onTimeChange","selectedProp","rightSidebarWidth","rightSidebarGroupRenderer","onReady","children","useMemo","getGroupIndex","grps","selectedKey","gridCanvasRef","itemsCanvasRef","overlayCanvasRef","interactionRef","outerRef","containerSize","setContainerSize","useState","container","obs","entries","entry","canvasWidth","viewStateRef","cursorXRef","hoveredItemIdRef","headerTimeStart","setHeaderTimeStart","headerTimeEnd","setHeaderTimeEnd","sidebarScrollTop","setSidebarScrollTop","headerTimerRef","syncHeaderState","vs","scheduleHeaderSync","intervalTree","layoutEngine","engine","gridLayer","itemsLayer","overlayLayer","interactionHandler","markerConfigs","configs","child","displayName","markersKey","m","markersRef","todayMarkerInterval","interval","propsRef","drawGrid","p","drawItems","calculateSnapX","deltaX","drawOverlay","interactionRender","origX","origWidth","targetGroupY","groupChanged","schedulerRef","scheduler","timer","prevMarkersKey","prevControlledStart","prevControlledEnd","callbackTimerRef","scheduleCallbacks","_b","zoomHandlerRef","zoomHandler","handleVerticalScroll","deltaY","maxScroll","newScrollTop","handleHorizontalScroll","flushSync","_c","el","handleWheel","rect","touchRef","getDistance","t1","t2","getCenter","handleTouchStart","handleTouchMove","newDistance","cursorTime","handleTouchEnd","handlePointerMove","newHoveredId","cr","handlePointerDown","handlePointerUp","validator","result","validatedTime","_d","_f","_e","handleDoubleClick","handleContextMenu","handlePointerLeave","headerChildren","headers","childProps","initialDrawDone","useImperativeHandle","timeStart","timeEnd","printSidebarWidth","headerRowHeight","headerHeight","currentPixelsPerMs","printDuration","timelineWidth","compositeWidth","compositeHeight","style","groupType","fontWeight","indent","drawHeaderRow","rowY","getLabel","unit","cursor","pxPerMs","nextCursor","printViewState","api","fullWidth","fullHeight","rs","gt","fw","fs","title","duration","units","row","hy","cur","endBound","next","sx","label","pv","canvasContainerStyle","canvasStyle","_jsxs","TimelineHeaders","className","_classNames","onZoomToInterval","enhancedChildren","enhanced","f","weekOfYear","DEFAULT_MIN_CELL_WIDTH","DateHeader","labelFormat","onIntervalClick","minCellWidth","minWidth","sampleStart","left","formatLabel","handleClick","_width","formatDefault","SidebarHeader","getRootProps","_Fragment","CustomHeader"],"mappings":"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","x_google_ignoreList":[12,18]}
|