@object-ui/plugin-gantt 6.2.3 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1,93 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/core"),require("@object-ui/react"),require("@objectstack/spec/ui"),require("@object-ui/plugin-detail"),require("@object-ui/components"),require("@object-ui/fields"),require("lucide-react"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@objectstack/spec/ui`,`@object-ui/plugin-detail`,`@object-ui/components`,`@object-ui/fields`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginGantt={},e.React,e.ObjectUICore,e.ObjectUIReact,e._objectstack_spec_ui,e._object_ui_plugin_detail,e.ObjectUIComponents,e._object_ui_fields,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c,l){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var u=Object.create,d=Object.defineProperty,f=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,m=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty,g=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=p(t),a=0,o=i.length,s;a<o;a++)s=i[a],!h.call(e,s)&&s!==n&&d(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=f(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:u(m(e)),g(t||!e||!e.__esModule?d(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var _={"gantt.column.taskName":`Task Name`,"gantt.column.start":`Start`,"gantt.column.end":`End`,"gantt.toolbar.prevPeriod":`Previous period`,"gantt.toolbar.nextPeriod":`Next period`,"gantt.toolbar.zoomIn":`Zoom in`,"gantt.toolbar.zoomOut":`Zoom out`,"gantt.toolbar.jumpToToday":`Jump to today`,"gantt.toolbar.today":`Today`,"gantt.toolbar.showTaskList":`Show task list`,"gantt.toolbar.hideTaskList":`Hide task list`},v=`gantt.column.taskName`;function y(e,t){let n=_[e]||e;if(t)for(let[e,r]of Object.entries(t))n=n.replace(`{{${e}}}`,String(r));return n}function b(){try{let e=(0,r.useObjectTranslation)();return e.t(v)===v?{t:y}:{t:e.t}}catch{return{t:y}}}function x(e){return e<640?35:e<1024?50:60}function S(e){return e<640?140:e<1024?220:320}function C(e){return e>=280}function w(e){return e<640?32:40}function T({tasks:e,startDate:n,endDate:r,onTaskClick:i,onTaskUpdate:a,className:s,inlineEdit:u=!1}){let{t:d}=b(),[f,p]=t.useState(new Date),m=t.useRef(null),{width:h}=(0,o.useResizeObserver)(m),g=h||(typeof window<`u`?window.innerWidth:1024),_=g<640,v=w(g),y=x(g),[T,E]=t.useState(null),D=T??y,[O,k]=t.useState(!1),A=t.useRef(!1);t.useEffect(()=>{!A.current&&_&&(k(!0),A.current=!0)},[_]);let j=O?0:S(g),M=C(j),[N,P]=t.useState(null),[F,I]=t.useState({}),[L,R]=t.useState(null),z=t.useRef(null);t.useEffect(()=>{z.current=L},[L]);let B=t.useRef(!1),V=t.useCallback(e=>{let t=1e3*60*60*24,n=t,r=e.dayDelta*t,i=new Date(e.originStart),a=new Date(e.originEnd);return e.mode===`move`?(i=new Date(e.originStart.getTime()+r),a=new Date(e.originEnd.getTime()+r)):e.mode===`resize-left`?(i=new Date(e.originStart.getTime()+r),a.getTime()-i.getTime()<n&&(i=new Date(a.getTime()-n))):e.mode===`resize-right`&&(a=new Date(e.originEnd.getTime()+r),a.getTime()-i.getTime()<n&&(a=new Date(i.getTime()+n))),{start:i,end:a}},[]);t.useEffect(()=>{if(!L)return;let t=e=>{let t=z.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(D,1));n!==t.dayDelta&&R({...t,dayDelta:n})},n=()=>{let t=z.current;if(t){if(t.dayDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&a){let{start:e,end:r}=V(t);a(n,{start:e,end:r})}B.current=!0,window.setTimeout(()=>{B.current=!1},0)}R(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[L,D,e,a,V]);let H=t.useCallback((e,t,n)=>{a&&(n.stopPropagation(),n.preventDefault(),R({taskId:e.id,mode:t,originStart:new Date(e.start),originEnd:new Date(e.end),originClientX:n.clientX,dayDelta:0}))},[a]),U=t.useMemo(()=>{let t=n?new Date(n):new Date,i=r?new Date(r):new Date;return!n&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!r&&e.length>0&&(i=new Date(Math.max(...e.map(e=>e.end.getTime()))),i.setDate(i.getDate()+14)),t.setHours(0,0,0,0),i.setHours(23,59,59,999),{start:t,end:i}},[n,r,e]),W=t.useMemo(()=>{let e=[],t=new Date(U.start);for(;t<=U.end;)e.push({date:new Date(t),label:t.getDate().toString(),isWeekend:t.getDay()===0||t.getDay()===6}),t.setDate(t.getDate()+1);return e},[U]),G=t.useRef(null),K=t.useRef(null),q=t.useRef(null),J=t.useRef(null),Y=t.useRef(null),X=t.useCallback(e=>{if(e.touches.length===2){let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY;Y.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:D}}},[D]),Z=t.useCallback(e=>{if(e.touches.length!==2||!Y.current)return;let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY,r=Math.max(1,Math.sqrt(t*t+n*n))/Y.current.baseDistance;E(Math.max(15,Math.min(120,Math.round(Y.current.baseColumn*r))))},[]),ee=t.useCallback(()=>{Y.current=null},[]),Q=t.useMemo(()=>{let e=new Date;if(e<U.start||e>U.end)return null;let t=(e.getTime()-U.start.getTime())/(1440*60*1e3);return Math.round(t*D)},[U,D]),te=t.useCallback(()=>{if(Q==null||!J.current)return;let e=Math.max(0,Q-J.current.clientWidth/2);J.current.scrollTo({left:e,behavior:`smooth`})},[Q]),ne=e=>{G.current&&(G.current.scrollLeft=e.currentTarget.scrollLeft),K.current&&(K.current.scrollTop=e.currentTarget.scrollTop)},$=e=>{U.end.getTime()-U.start.getTime();let t=D,n=1e3*60*60*24,r=e.start.getTime()-U.start.getTime(),i=e.end.getTime()-e.start.getTime();return{left:r/n*t,width:Math.max(i/n*t,t)}};return(0,l.jsxs)(`div`,{ref:m,className:(0,o.cn)(`flex flex-col h-full bg-background overflow-hidden min-w-0`,s),children:[(0,l.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card`,children:[(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":d(`gantt.toolbar.prevPeriod`),children:(0,l.jsx)(c.ChevronLeft,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":d(`gantt.toolbar.nextPeriod`),children:(0,l.jsx)(c.ChevronRight,{className:`h-4 w-4`})}),(0,l.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:U.start.toLocaleDateString(void 0,{month:`long`,year:`numeric`})})]}),(0,l.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,l.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>E(Math.max(15,D-10)),"aria-label":d(`gantt.toolbar.zoomOut`),children:(0,l.jsx)(c.ZoomOut,{className:`h-3 w-3`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>E(Math.min(120,D+10)),"aria-label":d(`gantt.toolbar.zoomIn`),children:(0,l.jsx)(c.ZoomIn,{className:`h-3 w-3`})})]}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>k(e=>!e),"aria-label":d(O?`gantt.toolbar.showTaskList`:`gantt.toolbar.hideTaskList`),"aria-pressed":O,"data-testid":`gantt-toggle-task-list`,children:O?(0,l.jsx)(c.PanelLeft,{className:`h-4 w-4`}):(0,l.jsx)(c.PanelLeftClose,{className:`h-4 w-4`})}),(0,l.jsx)(o.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:te,disabled:Q==null,"aria-label":d(`gantt.toolbar.jumpToToday`),"data-testid":`gantt-jump-today`,children:(0,l.jsx)(c.CalendarDays,{className:`h-4 w-4`})})]})]}),(0,l.jsxs)(`div`,{className:`flex flex-col flex-1 overflow-hidden`,children:[(0,l.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 sm:h-[50px]`,children:[(0,l.jsxs)(`div`,{className:`flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm`,style:{width:j,minWidth:j},children:[(0,l.jsx)(`div`,{className:`flex-1 truncate`,children:d(`gantt.column.taskName`)}),M&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:d(`gantt.column.start`)}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right`,children:d(`gantt.column.end`)})]})]}),(0,l.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:G,children:(0,l.jsx)(`div`,{className:`flex h-full`,style:{width:W.length*D},children:W.map((e,t)=>(0,l.jsxs)(`div`,{className:(0,o.cn)(`flex flex-col items-center justify-center border-r text-xs text-muted-foreground h-full`,e.isWeekend&&`bg-muted/50`),style:{width:D,minWidth:D},children:[(0,l.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,l.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.date.toLocaleDateString(void 0,{weekday:`narrow`})})]},t))})})]}),(0,l.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,l.jsx)(`div`,{className:`overflow-hidden border-r bg-card z-10 shadow-sm`,ref:K,style:{width:j,minWidth:j},children:e.map(e=>{let t=u&&N===e.id;return(0,l.jsxs)(`div`,{className:`group/task-row flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors touch-manipulation`,style:{height:v},onClick:()=>!t&&i?.(e),onDoubleClick:()=>{u&&a&&(P(e.id),I({title:e.title,start:e.start.toLocaleDateString(`en-CA`),end:e.end.toLocaleDateString(`en-CA`),progress:String(e.progress)}))},children:[(0,l.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,children:[(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:e.color||`#3b82f6`}}),t?(0,l.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:F.title||``,onChange:e=>I(t=>({...t,title:e.target.value})),onKeyDown:t=>{t.key===`Enter`?(a?.(e,{title:F.title,start:new Date(F.start),end:new Date(F.end),progress:Number(F.progress)||0}),P(null)):t.key===`Escape`&&P(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,l.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,l.jsx)(`span`,{className:`truncate`,children:e.title}),(0,l.jsxs)(`span`,{className:`text-[10px] text-muted-foreground sm:hidden`,children:[e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`}),` → `,e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})]})]})]}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!M,style:M?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:F.start||``,onChange:e=>I(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}),(0,l.jsx)(`div`,{className:`w-16 sm:w-20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!M,style:M?void 0:{display:`none`},children:t?(0,l.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:F.end||``,onChange:e=>I(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})})]},e.id)})}),(0,l.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{q.current=e,J.current=e},onScroll:ne,onTouchStart:X,onTouchMove:Z,onTouchEnd:ee,"data-testid":`gantt-timeline`,children:(0,l.jsxs)(`div`,{className:`relative`,style:{width:W.length*D},children:[Q!=null&&(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500/80 z-20 pointer-events-none`,style:{left:Q},"data-testid":`gantt-today-marker`,"aria-label":d(`gantt.toolbar.today`),children:(0,l.jsx)(`div`,{className:`absolute -top-2 -translate-x-1/2 left-0 text-[10px] font-semibold text-white bg-red-500 rounded-sm px-1 py-0.5 whitespace-nowrap`,children:d(`gantt.toolbar.today`)})}),(0,l.jsxs)(`div`,{className:`relative`,children:[(0,l.jsx)(`div`,{className:`absolute inset-0 flex pointer-events-none z-0`,children:W.map((e,t)=>(0,l.jsx)(`div`,{className:(0,o.cn)(`border-r h-full`,e.isWeekend&&`bg-muted/20`),style:{width:D,minWidth:D}},t))}),e.map(e=>{let t=$(e),n=L?.taskId===e.id,r=t;if(n&&L){let t=V(L);r=$({...e,start:t.start,end:t.end})}let s=!!a;return(0,l.jsxs)(`div`,{className:`relative border-b hover:bg-black/5`,style:{height:v},children:[n&&(0,l.jsx)(`div`,{className:`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm border border-dashed border-primary/60 pointer-events-none`,style:{left:t.left,width:t.width,opacity:.35},"aria-hidden":`true`}),(0,l.jsxs)(`div`,{className:(0,o.cn)(`absolute top-1 sm:top-2 h-[calc(100%-8px)] sm:h-[calc(100%-16px)] rounded-sm bg-primary border border-primary-foreground/20 shadow-sm hover:brightness-110 flex items-center px-2 group select-none`,s?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,n&&`ring-2 ring-primary/60 brightness-110 z-10`),style:{left:r.left,width:r.width,backgroundColor:e.color||`#3b82f6`},"data-testid":`gantt-task-bar-${e.id}`,onClick:()=>{B.current||i?.(e)},onPointerDown:s?t=>{t.button===0&&H(e,`move`,t)}:void 0,children:[s&&r.width>=14&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-left-${e.id}`,onPointerDown:t=>{t.button===0&&H(e,`resize-left`,t)},onClick:e=>e.stopPropagation()}),(0,l.jsx)(`div`,{className:`absolute right-0 top-0 bottom-0 w-1.5 cursor-ew-resize hover:bg-white/40`,"data-testid":`gantt-task-resize-right-${e.id}`,onPointerDown:t=>{t.button===0&&H(e,`resize-right`,t)},onClick:e=>e.stopPropagation()})]}),e.progress>0&&(0,l.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 bg-black/20 rounded-l-sm pointer-events-none`,style:{width:`${e.progress}%`}}),(0,l.jsx)(`span`,{className:`text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none`,children:n?`${V(L).start.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})} → ${V(L).end.toLocaleDateString(void 0,{month:`numeric`,day:`numeric`})}`:`${Math.round(e.progress)}%`})]})]},e.id)}),(0,l.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px bg-red-500 z-20 pointer-events-none`,style:{left:(new Date().getTime()-U.start.getTime())/(1e3*60*60*24)*D},children:(0,l.jsx)(`div`,{className:`w-2 h-2 rounded-full bg-red-500 -ml-[3px]`})})]})]})})]})]})]})}function E(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function D(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function O(e){let t=null;if(e.startDateField&&e.endDateField)return t={startDateField:e.startDateField,endDateField:e.endDateField,titleField:e.titleField||`name`,progressField:e.progressField,dependenciesField:e.dependenciesField||e.dependencyField,colorField:e.colorField},t;if(e.gantt&&(t=e.gantt),t){let e=i.GanttConfigSchema.safeParse(t);return e.success||console.warn(`[ObjectGantt] Invalid gantt configuration:`,e.error.format()),t}return null}var k=({schema:e,dataSource:i,className:c,onTaskClick:u,onRowClick:d,...f})=>{let[p,m]=(0,t.useState)([]),[h,g]=(0,t.useState)(!0),[_,v]=(0,t.useState)(null),[y,b]=(0,t.useState)(null),x=E(e),S=(0,t.useMemo)(()=>x,[JSON.stringify(x)]),C=O(e),w=S?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(g(!0),f.data&&Array.isArray(f.data)){m(f.data),g(!1);return}if(w&&S?.provider===`value`){m(S.items),g(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(S?.provider===`object`){let t=S.object,r=(0,n.buildExpandFields)(y?.fields);m((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:D(e.sort),...r.length>0?{$expand:r}:{}})))}else S?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),m([]));g(!1)}catch(e){v(e),g(!1)}})()},[S,i,w,e.filter,e.sort,y]),(0,t.useEffect)(()=>{!w&&i&&(async()=>{try{if(!i)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t)return;b(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,w,S]);let k=(0,t.useMemo)(()=>{if(!C||!p.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:a}=C,o=(e,t)=>{if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},c=e=>{let t=[o(e,n),e?.name,e?.title,e?.subject,e?.label,e?.account?.name,e?.opportunity?.name,e?.contact&&[e.contact.first_name,e.contact.last_name].filter(Boolean).join(` `),e?.id,e?._id];for(let e of t)if(e!=null&&String(e).trim()!==``)return String(e);return`Untitled`};return p.map((n,o)=>{let l=n[e],u=n[t],d=c(n),f=r?n[r]:0,p=i?n[i]:[],m=a?n[a]:void 0;if(!m){let e=n.status??n.state??n.priority??n.severity;if(e!=null&&e!==``){let t=(0,s.getSemanticColorName)(void 0,e);t&&(m=(0,s.getSemanticHex)(t))}}return{id:n.id||n._id||`task-${o}`,title:d,start:l?new Date(l):new Date,end:u?new Date(u):new Date,progress:Math.min(100,Math.max(0,f||0)),dependencies:Array.isArray(p)?p:[],color:m,data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[p,C]),A=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},j=A.mode===`drawer`||A.mode===`modal`||A.mode===`split`||A.mode===`popover`,M=(0,r.useNavigationOverlay)({navigation:A,objectName:e.objectName,onRowClick:j?void 0:d}),N=(0,t.useCallback)(async(t,n)=>{if(!C)return;let r=S?.provider===`object`?S.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=C,l={};if(n.start instanceof Date&&(l[a]=n.start.toISOString()),n.end instanceof Date&&(l[o]=n.end.toISOString()),typeof n.title==`string`&&s&&(l[s]=n.title),typeof n.progress==`number`&&c&&(l[c]=n.progress),Object.keys(l).length===0)return;let u=t.data?.id??t.data?._id??t.id;if(u==null)return;let d=p;m(e=>e.map(e=>String(e.id??e._id)===String(u)?{...e,...l}:e));try{await i.update(r,String(u),l)}catch(e){console.error(`[ObjectGantt] Failed to persist task update:`,e),m(d)}},[C,S,i,e.objectName,p]),[P,F]=(0,t.useState)(null),[I,L]=(0,t.useState)(!1),R=(0,t.useCallback)(e=>{F(e)},[]),z=(0,t.useCallback)(async()=>{if(!P)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t||!i?.delete){F(null);return}let n=P.data?.id??P.data?._id??P.id;if(n==null){F(null);return}L(!0);let r=p;m(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),F(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),m(r),F(null)}finally{L(!1)}},[P,S,i,e.objectName,p]);return h?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):_?(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,_.message]})})}):C?(0,l.jsxs)(`div`,{className:c,children:[(0,l.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:(0,l.jsx)(T,{tasks:k,onTaskClick:e=>{M.handleClick(e.data),u?.(e.data)},onTaskUpdate:N,onTaskDelete:R,inlineEdit:!0})}),M.isOverlay&&M.isOpen&&M.selectedRecord&&(()=>{let t=S?.provider===`object`?S.object:e.objectName,n=M.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let o=C?.titleField?String(n[C.titleField]??`Task Details`):`Task Details`;return(0,l.jsx)(a.RecordDetailDrawer,{open:!0,onClose:M.close,title:o,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:y,width:M.width,fullPageHref:(0,a.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),m(t=>t.map(t=>String(t.id??t._id)===String(r)?{...t,[e]:n}:t)))},onDelete:async()=>{i?.delete&&(await i.delete(t,String(r)),m(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,l.jsx)(o.AlertDialog,{open:!!P,onOpenChange:e=>{!e&&!I&&F(null)},children:(0,l.jsxs)(o.AlertDialogContent,{children:[(0,l.jsxs)(o.AlertDialogHeader,{children:[(0,l.jsx)(o.AlertDialogTitle,{children:`Delete this task?`}),(0,l.jsx)(o.AlertDialogDescription,{children:P?(0,l.jsxs)(l.Fragment,{children:[`"`,P.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,l.jsxs)(o.AlertDialogFooter,{children:[(0,l.jsx)(o.AlertDialogCancel,{disabled:I,children:`Cancel`}),(0,l.jsx)(o.AlertDialogAction,{onClick:e=>{e.preventDefault(),z()},disabled:I,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:I?`Deleting…`:`Delete`})]})]})})]}):(0,l.jsx)(`div`,{className:c,children:(0,l.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,l.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},A=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,l.jsx)(k,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,A,{namespace:`plugin-gantt`,label:`Object Gantt`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),n.ComponentRegistry.register(`gantt`,A,{namespace:`view`,label:`Gantt View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),e.GanttView=T,e.ObjectGantt=k,e.ObjectGanttRenderer=A});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("react"),require("@object-ui/core"),require("@object-ui/react"),require("@objectstack/spec/ui"),require("@object-ui/i18n"),require("@object-ui/plugin-detail"),require("@object-ui/components"),require("@object-ui/fields"),require("lucide-react"),require("react/jsx-runtime")):typeof define==`function`&&define.amd?define([`exports`,`react`,`@object-ui/core`,`@object-ui/react`,`@objectstack/spec/ui`,`@object-ui/i18n`,`@object-ui/plugin-detail`,`@object-ui/components`,`@object-ui/fields`,`lucide-react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ObjectUIPluginGantt={},e.React,e.ObjectUICore,e.ObjectUIReact,e._objectstack_spec_ui,e._object_ui_i18n,e._object_ui_plugin_detail,e.ObjectUIComponents,e._object_ui_fields,e.LucideReact,e.react_jsx_runtime))})(this,function(e,t,n,r,i,a,o,s,c,l,u){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var d=Object.create,f=Object.defineProperty,p=Object.getOwnPropertyDescriptor,m=Object.getOwnPropertyNames,h=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty,_=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=m(t),a=0,o=i.length,s;a<o;a++)s=i[a],!g.call(e,s)&&s!==n&&f(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=p(t,s))||r.enumerable});return e};t=((e,t,n)=>(n=e==null?{}:d(h(e)),_(t||!e||!e.__esModule?f(n,`default`,{value:e,enumerable:!0}):n,e)))(t,1);var v=1e3*60*60*24,y=e=>e.toISOString().slice(0,10);function b(e,t){if(t.skipWeekends){let t=e.getUTCDay();if(t===0||t===6)return!1}return!(t.holidays&&t.holidays.has(y(e)))}function x(e){let t=new Date(e);return t.setUTCHours(0,0,0,0),t}function ee(e,t){let n=x(e);for(;!b(n,t);)n=new Date(n.getTime()+v);return n.getTime()}function te(e,t,n){if(t<=e)return 0;let r=0,i=x(e),a=x(t).getTime();for(;i.getTime()<a;)b(i,n)&&r++,i=new Date(i.getTime()+v);return r}function S(e,t,n){if(t<=0)return x(e).getTime();let r=x(e),i=t;for(;i>0;)b(r,n)&&i--,r=new Date(r.getTime()+v);return r.getTime()}function C(e,t,n){if(t<=0)return x(e).getTime();let r=x(e),i=t;for(;i>0;)r=new Date(r.getTime()-v),b(r,n)&&i--;return r.getTime()}var w=e=>String(e);function T(e){return e===`ss`||e===`ff`||e===`sf`?e:`fs`}function ne(e){let t=new Set(e.map(e=>w(e.id))),n=[];for(let r of e){let e=w(r.id);for(let i of r.dependencies??[]){let r=typeof i==`object`&&!!i,a=r?i.id:i;if(a==null||a===``)continue;let o=w(a);o===e||!t.has(o)||n.push({pred:o,succ:e,type:T(r?i.type:void 0)})}}return n}function re(e){let t=new Set;for(let n of e)n.parent!=null&&n.parent!==``&&t.add(w(n.parent));return t}function E(e,t){let n=new Map,r=new Map;for(let t of e)n.set(t,0),r.set(t,[]);for(let e of t)r.get(e.pred).push(e.succ),n.set(e.succ,(n.get(e.succ)??0)+1);let i=e.filter(e=>(n.get(e)??0)===0),a=[];for(;i.length;){let e=i.shift();a.push(e);for(let t of r.get(e)??[]){let e=(n.get(t)??0)-1;n.set(t,e),e===0&&i.push(t)}}if(a.length<e.length){let t=new Set(a);for(let n of e)t.has(n)||a.push(n);return{order:a,hasCycle:!0}}return{order:a,hasCycle:!1}}function ie(e,t){let n={criticalIds:new Set,criticalEdges:new Set};if(!e.length)return n;let r=new Map;for(let n of e){let e=t?te(n.start.getTime(),n.end.getTime(),t):(n.end.getTime()-n.start.getTime())/v;r.set(w(n.id),Number.isFinite(e)&&e>0?e:0)}let i=ne(e),a=e.map(e=>w(e.id)),{order:o,hasCycle:s}=E(a,i);if(s)return n;let c=new Map,l=new Map;for(let e of a)c.set(e,[]),l.set(e,[]);for(let e of i)c.get(e.succ).push(e),l.get(e.pred).push(e);let u=new Map,d=new Map;for(let e of o){let t=0;for(let n of c.get(e)??[])t=Math.max(t,d.get(n.pred)??0);u.set(e,t),d.set(e,t+(r.get(e)??0))}let f=Math.max(0,...a.map(e=>d.get(e)??0)),p=new Map,m=new Map;for(let e=o.length-1;e>=0;e--){let t=o[e],n=l.get(t)??[],i=f;n.length&&(i=Math.min(...n.map(e=>m.get(e.succ)??f))),p.set(t,i),m.set(t,i-(r.get(t)??0))}let h=1e-6,g=new Set;for(let e of a){let t=(m.get(e)??0)-(u.get(e)??0);Math.abs(t)<=h&&g.add(e)}let _=new Set;for(let e of i)_.add(e.pred),_.add(e.succ);for(let e of[...g])!_.has(e)&&(r.get(e)??0)===0&&g.delete(e);let y=new Set;for(let e of i)!g.has(e.pred)||!g.has(e.succ)||Math.abs((d.get(e.pred)??0)-(u.get(e.succ)??0))<=h&&y.add(`${e.pred}->${e.succ}`);return{criticalIds:g,criticalEdges:y}}function ae(e,t){if(!e.length)return[];let n=ne(e),r=e.map(e=>w(e.id)),{order:i,hasCycle:a}=E(r,n);if(a)return[];let o=re(e),s=new Map;for(let t of e)s.set(w(t.id),t);let c=new Map;for(let e of r)c.set(e,[]);for(let e of n)c.get(e.succ).push(e);let l=new Map,u=new Map;for(let t of e)l.set(w(t.id),t.start.getTime()),u.set(w(t.id),t.end.getTime());for(let e of i){let n=s.get(e);if(!n)continue;let r=t?te(l.get(e),u.get(e),t):u.get(e)-l.get(e),i=n.start.getTime();for(let n of c.get(e)??[]){let e=l.get(n.pred),a=u.get(n.pred),o;switch(n.type){case`ss`:o=e;break;case`ff`:o=t?C(a,r,t):a-r;break;case`sf`:o=t?C(e,r,t):e-r;break;default:o=a;break}o>i&&(i=o)}if(!o.has(e))if(t){let n=ee(i,t);l.set(e,n),u.set(e,S(n,r,t))}else l.set(e,i),u.set(e,i+r)}let d=[];for(let t of e){let e=w(t.id);if(o.has(e))continue;let n=l.get(e),r=u.get(e);(n!==t.start.getTime()||r!==t.end.getTime())&&d.push({id:e,start:new Date(n),end:new Date(r)})}return d}var oe={"gantt.column.taskName":`Task Name`,"gantt.column.start":`Start`,"gantt.column.end":`End`,"gantt.toolbar.prevPeriod":`Previous period`,"gantt.toolbar.nextPeriod":`Next period`,"gantt.toolbar.zoomIn":`Zoom in`,"gantt.toolbar.zoomOut":`Zoom out`,"gantt.toolbar.jumpToToday":`Jump to today`,"gantt.toolbar.today":`Today`,"gantt.toolbar.thisWeek":`This week`,"gantt.toolbar.thisMonth":`This month`,"gantt.toolbar.exportPdf":`Export PDF`,"gantt.toolbar.saveLayout":`Save layout`,"gantt.toolbar.showTaskList":`Show task list`,"gantt.toolbar.hideTaskList":`Hide task list`,"gantt.toolbar.viewMode":`Timeline granularity`,"gantt.toolbar.enterFullscreen":`Enter fullscreen`,"gantt.toolbar.exitFullscreen":`Exit fullscreen`,"gantt.toolbar.criticalPath":`Highlight critical path`,"gantt.toolbar.autoSchedule":`Auto-schedule dependencies`,"gantt.toolbar.exportPng":`Export as PNG`,"gantt.toolbar.undo":`Undo`,"gantt.toolbar.redo":`Redo`,"gantt.viewMode.day":`Day`,"gantt.viewMode.week":`Week`,"gantt.viewMode.month":`Month`,"gantt.viewMode.quarter":`Quarter`,"gantt.viewMode.year":`Year`,"gantt.row.expand":`Expand`,"gantt.row.collapse":`Collapse`,"gantt.row.locate":`Locate on timeline`,"gantt.aria.taskList":`Task list`,"gantt.tooltip.days":`d`,"gantt.menu.view":`View details`,"gantt.menu.edit":`Edit inline`,"gantt.menu.delete":`Delete`,"gantt.menu.addPredecessor":`Add predecessor…`,"gantt.menu.addSuccessor":`Add successor…`,"gantt.menu.removeDependency":`Remove dependency`,"gantt.menu.noCandidates":`No available tasks`,"gantt.linkType.fs":`Finish → Start`,"gantt.linkType.ss":`Start → Start`,"gantt.linkType.ff":`Finish → Finish`,"gantt.linkType.sf":`Start → Finish`,"gantt.linkEnd.start":`start`,"gantt.linkEnd.end":`end`,"gantt.conflict.title":`Schedule conflict`,"gantt.conflict.body":`This move conflicts with dependency constraints. Auto-reschedule {count} affected task(s)?`,"gantt.conflict.confirm":`Auto-reschedule`,"gantt.conflict.cancel":`Keep as is`,"gantt.resource.header":`Resource`,"gantt.resource.peak":`Peak`,"gantt.resource.over":`overloaded`,"gantt.resource.empty":`No tasks to allocate.`,"gantt.readOnly":`Read-only`,"gantt.readOnlyHint":`Editing is disabled for this view.`};function D(e,t){let n=oe[e]||e;if(t)for(let[e,r]of Object.entries(t))n=n.replace(`{{${e}}}`,String(r));return n}function se(){try{let e=(0,r.useObjectTranslation)();return{t:(t,n)=>{let r=e.t(t,n);return typeof r==`string`&&r!==t?r:D(t,n)},language:e.language}}catch{return{t:D,language:void 0}}}function ce(e){return 110}function le(e){return e<640?140:e<1024?220:320}function ue(e){return e>=280}function de(e){return e<640?32:40}var O=[`day`,`week`,`month`,`quarter`,`year`],fe={day:1,week:7,month:30.44,quarter:91.31,year:365.25},pe=1e3*60*60*24;function k(e,t){let n=new Date(e);return n.setHours(0,0,0,0),t===`week`?n.setDate(n.getDate()-(n.getDay()+6)%7):t===`month`?n.setDate(1):t===`quarter`?n.setMonth(Math.floor(n.getMonth()/3)*3,1):t===`year`&&n.setMonth(0,1),n}function me(e,t,n){let r=e.length-1,i=0;for(;i<r&&e[i+1]<t;)i++;let a=i;for(;a<r&&e[a]<n;)a++;return{start:i,end:a}}function A(e,t,n){let r=new Date(e);if(n===`day`)r.setDate(r.getDate()+t);else if(n===`week`)r.setDate(r.getDate()+t*7);else{let e=t*(n===`month`?1:n===`quarter`?3:12),i=r.getDate();r.setDate(1),r.setMonth(r.getMonth()+e);let a=new Date(r.getFullYear(),r.getMonth()+1,0).getDate();r.setDate(Math.min(i,a))}return r}function he(e,t,n,r=2){return new Promise(i=>{let a=new Blob([e],{type:`image/svg+xml;charset=utf-8`}),o=URL.createObjectURL(a),s=new Image;s.onload=()=>{let e=document.createElement(`canvas`);e.width=t*r,e.height=n*r;let a=e.getContext(`2d`);a&&(a.fillStyle=`#ffffff`,a.fillRect(0,0,e.width,e.height),a.scale(r,r),a.drawImage(s,0,0)),URL.revokeObjectURL(o),i(e)},s.onerror=()=>{URL.revokeObjectURL(o),i(null)},s.src=o})}function ge(e,t){let n=document.createElement(`a`);n.href=URL.createObjectURL(e),n.download=t,document.body.appendChild(n),n.click(),n.remove(),setTimeout(()=>URL.revokeObjectURL(n.href),1e3)}function _e(e,t,n){let r=e=>{let t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n)&255;return t},i=`q ${t} 0 0 ${n} 0 0 cm /Im0 Do Q`,a=[],o=[],s=0,c=e=>{a.push(e),s+=e.length},l=()=>{o.push(s)};c(r(`%PDF-1.3
2
+ %ÿÿÿÿ
3
+ `)),l(),c(r(`1 0 obj
4
+ << /Type /Catalog /Pages 2 0 R >>
5
+ endobj
6
+ `)),l(),c(r(`2 0 obj
7
+ << /Type /Pages /Kids [3 0 R] /Count 1 >>
8
+ endobj
9
+ `)),l(),c(r(`3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${t} ${n}] /Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>\nendobj\n`)),l(),c(r(`4 0 obj\n<< /Type /XObject /Subtype /Image /Width ${t} /Height ${n} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ${e.length} >>\nstream\n`)),c(e),c(r(`
10
+ endstream
11
+ endobj
12
+ `)),l(),c(r(`5 0 obj\n<< /Length ${i.length} >>\nstream\n${i}\nendstream\nendobj\n`));let u=s,d=`xref
13
+ 0 6
14
+ 0000000000 65535 f
15
+ `;for(let e of o)d+=`${String(e).padStart(10,`0`)} 00000 n \n`;return d+=`trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n${u}\n%%EOF\n`,c(r(d)),new Blob(a,{type:`application/pdf`})}function ve(e){let t=e.slice(e.indexOf(`,`)+1),n=atob(t),r=new Uint8Array(n.length);for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return r}var ye=`gantt-layout:`;function be(e){if(!e||typeof window>`u`)return null;try{let t=window.localStorage.getItem(ye+e);if(!t)return null;let n=JSON.parse(t),r=n.viewMode&&O.includes(n.viewMode)?n.viewMode:null;if(!r)return null;let i=typeof n.columnWidth==`number`&&isFinite(n.columnWidth)?n.columnWidth:null,a=typeof n.taskListWidth==`number`&&isFinite(n.taskListWidth)?n.taskListWidth:null;return{viewMode:r,columnWidth:i,taskListCollapsed:!!n.taskListCollapsed,taskListWidth:a}}catch{return null}}function xe(e,t){if(!(typeof window>`u`))try{window.localStorage.setItem(ye+e,JSON.stringify(t))}catch{}}function Se({tasks:e,viewMode:n,startDate:r,endDate:i,markers:a,onTaskClick:o,onTaskUpdate:c,onTaskDelete:d,onViewChange:f,onDependencyCreate:p,onDependencyDelete:m,onTaskReorder:h,className:g,inlineEdit:_=!1,autoSchedule:v=!1,rescheduleOnConflict:y=!1,criticalPathDefault:b=!1,workingCalendar:x,showBaselines:ee=!0,readOnly:te=!1,mobileReadOnly:S=!1,groupBy:C,ungroupedLabel:w=`Ungrouped`,defaultCollapsedDepth:T,persistLayoutKey:ne,onLayoutChange:re}){let{t:E,language:oe}=se(),D=oe||void 0,[ye,Se]=t.useState(new Date),Ce=t.useRef(null),{width:we}=(0,s.useResizeObserver)(Ce),j=we||(typeof window<`u`?window.innerWidth:1024),Te=j<640,M=te||S&&Te,N=M?void 0:c,Ee=M?void 0:d,P=M?void 0:p,De=M?void 0:m,Oe=M?void 0:h,ke=M?!1:_,Ae=M?!1:v,je=M?!1:y,F=de(j),Me=ce(j),Ne=t.useRef(void 0);Ne.current===void 0&&(Ne.current=be(ne));let Pe=Ne.current,[Fe,Ie]=t.useState(Pe?Pe.columnWidth:null),[Le,Re]=t.useState(Pe?Pe.taskListWidth??null:null),[I,ze]=t.useState(n&&O.includes(n)?n:Pe?.viewMode??`day`);t.useEffect(()=>{n&&O.includes(n)&&ze(n)},[n]);let Be=t.useRef(null),Ve=t.useRef(null),He=t.useRef(!0),[Ue,We]=t.useState(Pe?Pe.taskListCollapsed:!1),Ge=t.useRef(!1);t.useEffect(()=>{!Ge.current&&Te&&(We(!0),Ge.current=!0)},[Te]);let Ke=Math.max(160,j-200),L=Ue?0:Le==null?le(j):Math.max(160,Math.min(Le,Ke)),qe=t.useMemo(()=>{if(Fe!=null||i||e.length===0)return null;let t=r?new Date(r):new Date(Math.min(...e.map(e=>e.start.getTime()))),n=new Date(Math.max(...e.map(e=>e.end.getTime())));r||t.setDate(t.getDate()-7),n.setDate(n.getDate()+14),t=k(t,I),n.setHours(23,59,59,999);let a=Math.max(1,(n.getTime()-t.getTime())/pe),o=Math.max(0,j-L);if(o<=0)return null;let s=o/a*fe[I];if(s<=Me)return null;let c=Math.min(s,o*.6);return c>Me?c:null},[Fe,e,r,i,I,j,L,Me]),R=Fe??qe??Me,Je=R/fe[I],Ye=ue(L),[Xe,Ze]=t.useState(null),[Qe,$e]=t.useState({}),[et,tt]=t.useState(null),z=t.useMemo(()=>{if(!C)return e;let t=new Set;for(let n of e){let e=n.parent!=null&&n.parent!==``?String(n.parent):null;e&&t.add(e)}let n=new Map;for(let r of e){if(t.has(String(r.id)))continue;let e=C(r),i=e?String(e.key):`__ungrouped__`,a=e?e.label:w,o=n.get(i);o||(o={key:i,label:a,items:[]},n.set(i,o)),o.items.push(r)}let r=[];for(let e of n.values()){let t=`__group__${e.key}`,n=e.items[0];r.push({id:t,title:e.label,start:n.start,end:n.end,progress:0,type:`summary`,parent:null,data:{__group:!0}});for(let n of e.items)r.push({...n,parent:t})}return r},[C,e,w]),nt=t.useMemo(()=>{let e=new Set(z.map(e=>String(e.id))),t=new Map;for(let n of z){let r=n.parent!=null&&n.parent!==``?String(n.parent):null;if(r&&r!==String(n.id)&&e.has(r)){let e=t.get(r);e?e.push(n):t.set(r,[n])}}return t},[z]),rt=t.useMemo(()=>{let e=new Map;for(let t of z)e.set(String(t.id),t);return e},[z]),it=t.useCallback(e=>{let t=[],n=new Set,r=e=>{for(let i of nt.get(e)??[]){let e=String(i.id);n.has(e)||(n.add(e),t.push(i),r(e))}};return r(String(e)),t},[nt]),[B,at]=t.useState(null),ot=t.useRef(null);t.useEffect(()=>{ot.current=B},[B]);let st=t.useRef(!1),ct=t.useCallback(e=>{let t=pe,n=(e,t)=>tn.current?tn.current(e,t):A(e,t,I),r=new Date(e.originStart),i=new Date(e.originEnd);return e.mode===`move`?(r=n(e.originStart,e.unitDelta),i=new Date(e.originEnd.getTime()+(r.getTime()-e.originStart.getTime()))):e.mode===`resize-left`?(r=n(e.originStart,e.unitDelta),i.getTime()-r.getTime()<t&&(r=new Date(i.getTime()-t))):e.mode===`resize-right`&&(i=n(e.originEnd,e.unitDelta),i.getTime()-r.getTime()<t&&(i=new Date(r.getTime()+t))),{start:r,end:i}},[I]),lt=t.useRef(e);lt.current=e;let ut=t.useRef([]),dt=t.useRef([]),[ft,pt]=t.useState(0),V=t.useCallback(e=>{if(!N)return;let t=[];for(let{task:n,changes:r}of e){let e={},i={},a=!1;for(let t of Object.keys(r)){let o=r[t],s=n[t],c=o instanceof Date&&s instanceof Date?o.getTime()===s.getTime():o===s;e[t]=s,i[t]=o,c||(a=!0)}N(n,r),a&&t.push({taskId:String(n.id),before:e,after:i})}t.length&&(ut.current.push(t),dt.current=[],pt(e=>e+1))},[N]),[mt,ht]=t.useState(null),gt=t.useCallback(e=>{if(!je)return;let t=new Map;for(let{task:n,changes:r}of e)t.set(String(n.id),{start:r.start??n.start,end:r.end??n.end});let n=ae(lt.current.map(e=>{let n=t.get(String(e.id));return n?{...e,start:n.start,end:n.end}:e}),x).filter(e=>{let n=t.get(e.id);return!n||e.start.getTime()!==n.start.getTime()||e.end.getTime()!==n.end.getTime()});n.length&&ht(n)},[je,x]),_t=t.useCallback(()=>{if(!mt)return;let e=mt.map(e=>{let t=lt.current.find(t=>String(t.id)===e.id);return t?{task:t,changes:{start:e.start,end:e.end}}:null}).filter(Boolean);e.length&&V(e),ht(null)},[mt,V]),vt=t.useCallback((e,t)=>{if(N)for(let n of e){let e=lt.current.find(e=>String(e.id)===n.taskId);e&&N(e,t===`undo`?n.before:n.after)}},[N]),yt=t.useCallback(()=>{let e=ut.current.pop();e&&(vt(e,`undo`),dt.current.push(e),pt(e=>e+1))},[vt]),bt=t.useCallback(()=>{let e=dt.current.pop();e&&(vt(e,`redo`),ut.current.push(e),pt(e=>e+1))},[vt]),{canUndo:xt,canRedo:St}=t.useMemo(()=>({canUndo:ut.current.length>0,canRedo:dt.current.length>0}),[ft]);t.useEffect(()=>{if(!B)return;let t=e=>{let t=ot.current;if(!t)return;let n=Math.round((e.clientX-t.originClientX)/Math.max(R,1));n!==t.unitDelta&&at({...t,unitDelta:n})},n=()=>{let t=ot.current;if(t){if(t.unitDelta!==0){let n=e.find(e=>e.id===t.taskId);if(n&&N){let{start:e,end:r}=ct(t);if(t.group){let r=e.getTime()-t.originStart.getTime(),i=[n,...it(n.id)].map(e=>({task:e,changes:{start:new Date(e.start.getTime()+r),end:new Date(e.end.getTime()+r)}}));V(i),gt(i)}else{let t=[{task:n,changes:{start:e,end:r}}];V(t),gt(t)}}st.current=!0,window.setTimeout(()=>{st.current=!1},0)}at(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[B,R,e,N,ct,it,V,gt]);let Ct=t.useCallback((e,t,n,r)=>{!N||e.data?.__group||(n.stopPropagation(),n.preventDefault(),at({taskId:e.id,mode:t,group:r?.group??!1,originStart:new Date(r?.originStart??e.start),originEnd:new Date(r?.originEnd??e.end),originClientX:n.clientX,unitDelta:0}))},[N]),[wt,Tt]=t.useState(null),Et=t.useRef(null);t.useEffect(()=>{Et.current=wt},[wt]),t.useEffect(()=>{if(!wt)return;let t=e=>{let t=Et.current;if(!t)return;let n=Math.min(100,Math.max(0,Math.round(t.originProgress+(e.clientX-t.originClientX)/Math.max(t.barWidth,1)*100)));n!==t.value&&Tt({...t,value:n})},n=()=>{let t=Et.current;if(t){if(t.value!==t.originProgress){let n=e.find(e=>e.id===t.taskId);n&&N&&V([{task:n,changes:{progress:t.value}}]),st.current=!0,window.setTimeout(()=>{st.current=!1},0)}Tt(null)}};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[wt,e,N,V]);let Dt=t.useRef(null),[H,Ot]=t.useState(null),kt=t.useRef(null);t.useEffect(()=>{kt.current=H},[H]),t.useEffect(()=>{if(!H)return;let t=e=>{let t=Dt.current?.getBoundingClientRect();if(!t)return;let n=e.clientX-t.left,r=e.clientY-t.top;Ot(e=>e&&{...e,x:n,y:r})},n=()=>{let t=kt.current;if(t&&t.targetId!=null&&String(t.targetId)!==String(t.sourceId)&&P){let n=e.find(e=>String(e.id)===String(t.sourceId)),r=e.find(e=>String(e.id)===String(t.targetId)),i=t.targetEnd??`start`,a=`${t.sourceEnd===`end`?`f`:`s`}${i===`end`?`f`:`s`}`;n&&r&&P(n,r,a)}st.current=!0,window.setTimeout(()=>{st.current=!1},0),Ot(null)};return window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n),()=>{window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)}},[H,e,P]);let[At,jt]=t.useState(null),Mt=t.useRef(null);t.useEffect(()=>{if(!At)return;let e=e=>{Mt.current&&e.target instanceof Node&&Mt.current.contains(e.target)||jt(null)},t=e=>{e.key===`Escape`&&jt(null)};return window.addEventListener(`pointerdown`,e,!0),window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`pointerdown`,e,!0),window.removeEventListener(`keydown`,t)}},[At]);let[U,Nt]=t.useState(null),Pt=t.useRef(null);t.useEffect(()=>{if(!U)return;let e=e=>{Pt.current&&e.target instanceof Node&&Pt.current.contains(e.target)||Nt(null)},t=e=>{e.key===`Escape`&&Nt(null)};return window.addEventListener(`pointerdown`,e,!0),window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`pointerdown`,e,!0),window.removeEventListener(`keydown`,t)}},[U]);let[W,Ft]=t.useState(null),It=t.useRef(null);t.useEffect(()=>{if(!W)return;let e=e=>{It.current&&e.target instanceof Node&&It.current.contains(e.target)||Ft(null)},t=e=>{e.key===`Escape`&&Ft(null)};return window.addEventListener(`pointerdown`,e,!0),window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`pointerdown`,e,!0),window.removeEventListener(`keydown`,t)}},[W]);let[Lt,Rt]=t.useState(null),zt=!!(o||N||P||Ee),Bt=t.useCallback((e,t)=>{t.preventDefault(),t.stopPropagation(),Rt(e.id),zt&&jt({x:t.clientX,y:t.clientY,taskId:e.id})},[zt]),Vt=t.useCallback((e,t,n,r)=>{r.preventDefault(),r.stopPropagation(),!(!P&&!De)&&Nt({x:r.clientX,y:r.clientY,sourceId:e,targetId:t,type:n})},[P,De]),[Ht,Ut]=t.useState(()=>new Set),Wt=t.useCallback(e=>{Ut(t=>{let n=new Set(t),r=String(e);return n.has(r)?n.delete(r):n.add(r),n})},[]),Gt=t.useRef(!1);t.useEffect(()=>{if(Gt.current||T==null||z.length===0)return;Gt.current=!0;let e=new Map(z.map(e=>[String(e.id),e])),t=new Set;for(let n of z){let r=n.parent!=null&&n.parent!==``?String(n.parent):null;r&&r!==String(n.id)&&e.has(r)&&t.add(r)}let n=t=>{let n=0,r=new Set([String(t.id)]),i=t.parent!=null&&t.parent!==``?e.get(String(t.parent)):void 0;for(;i&&!r.has(String(i.id));)n+=1,r.add(String(i.id)),i=i.parent!=null&&i.parent!==``?e.get(String(i.parent)):void 0;return n},r=new Set;for(let e of z){let i=String(e.id);t.has(i)&&n(e)>=T&&r.add(i)}r.size&&Ut(e=>e.size?e:r)},[T,z]);let G=t.useMemo(()=>{let e=new Set(z.map(e=>String(e.id))),t=new Map,n=[];for(let r of z){let i=r.parent!=null&&r.parent!==``?String(r.parent):null;if(i&&i!==String(r.id)&&e.has(i)){let e=t.get(i);e?e.push(r):t.set(i,[r])}else n.push(r)}let r=new Map,i=(e,n)=>{let a=String(e.id),o=r.get(a);if(o)return o;let s=t.get(a)??[],c;if(!s.length||n.has(a))c={start:e.start,end:e.end,progress:e.progress};else{n.add(a);let e=null,t=null,r=0,o=0;for(let a of s){let s=i(a,n);(!e||s.start<e)&&(e=s.start),(!t||s.end>t)&&(t=s.end);let c=Math.max(s.end.getTime()-s.start.getTime(),pe);r+=c*s.progress,o+=c}n.delete(a),c={start:e,end:t,progress:o?r/o:0}}return r.set(a,c),c},a=[],o=new Set,s=e=>{for(let n of t.get(String(e.id))??[])o.has(String(n.id))||(o.add(String(n.id)),s(n))},c=(e,n)=>{let r=String(e.id);if(o.has(r))return;o.add(r);let l=t.get(r)??[],u=l.length>0,d=u||e.type===`summary`,f=u?i(e,new Set):{start:e.start,end:e.end,progress:e.progress},p=!d&&(e.type===`milestone`||e.end.getTime()<=e.start.getTime());if(a.push({task:e,depth:n,hasChildren:u,isSummary:d,isMilestone:p,...f}),u)if(Ht.has(r))s(e);else for(let e of l)c(e,n+1)};for(let e of n)c(e,0);for(let e of z)o.has(String(e.id))||c(e,0);return a},[z,Ht]),Kt=t.useCallback(e=>{if(e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement)return;if((e.ctrlKey||e.metaKey)&&(e.key===`z`||e.key===`Z`)){e.preventDefault(),e.shiftKey?bt():yt();return}if((e.ctrlKey||e.metaKey)&&(e.key===`y`||e.key===`Y`)){e.preventDefault(),bt();return}if(!G.length)return;let t=Lt==null?-1:G.findIndex(e=>String(e.task.id)===String(Lt));if(e.key===`ArrowDown`||e.key===`ArrowUp`){e.preventDefault();let n=e.key===`ArrowDown`?Math.min(G.length-1,t+1):Math.max(0,t<=0?0:t-1);Rt(G[n].task.id);let r=X.current;if(r){let e=n*F;e<r.scrollTop?r.scrollTop=e:e+F>r.scrollTop+r.clientHeight&&(r.scrollTop=e+F-r.clientHeight)}return}if(t<0)return;let n=G[t];e.key===`Enter`?(e.preventDefault(),o?.(n.task)):e.key===`Delete`||e.key===`Backspace`?Ee&&(e.preventDefault(),Ee(n.task)):(e.key===`ArrowRight`&&n.hasChildren&&Ht.has(String(n.task.id))||e.key===`ArrowLeft`&&n.hasChildren&&!Ht.has(String(n.task.id)))&&(e.preventDefault(),Wt(n.task.id))},[G,Lt,o,Ee,Ht,Wt,F,yt,bt]),K=t.useMemo(()=>{let t=r?new Date(r):new Date,n=i?new Date(i):new Date;return!r&&e.length>0&&(t=new Date(Math.min(...e.map(e=>e.start.getTime()))),t.setDate(t.getDate()-7)),!i&&e.length>0&&(n=new Date(Math.max(...e.map(e=>e.end.getTime()))),n.setDate(n.getDate()+14)),t=k(t,I),n.setHours(23,59,59,999),{start:t,end:n}},[r,i,e,I]),qt=I===`day`&&!!x&&(!!x.skipWeekends||!!(x.holidays&&x.holidays.size)),Jt=t.useCallback(e=>{if(!x)return!0;if(x.skipWeekends){let t=e.getDay();if(t===0||t===6)return!1}if(x.holidays&&x.holidays.size){let t=`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,`0`)}-${String(e.getDate()).padStart(2,`0`)}`;if(x.holidays.has(t))return!1}return!0},[x]),q=t.useMemo(()=>{let e=[],t=new Date(K.start);for(;t<=K.end;){let n=A(t,1,I);if(qt&&!Jt(t)){t=n;continue}let r=(n.getTime()-t.getTime())/pe*Je,i,a;I===`day`?(i=String(t.getDate()),a=t.toLocaleDateString(D,{weekday:`narrow`})):i=I===`week`?t.toLocaleDateString(D,{month:`numeric`,day:`numeric`}):I===`month`?t.toLocaleDateString(D,{month:`short`}):I===`quarter`?`Q${Math.floor(t.getMonth()/3)+1}`:String(t.getFullYear()),e.push({date:new Date(t),label:i,sublabel:a,isWeekend:I===`day`&&(t.getDay()===0||t.getDay()===6),width:r}),t=n}return e},[K,I,Je,D,qt,Jt]),J=t.useMemo(()=>{let e=Array(q.length+1),t=0;for(let n=0;n<q.length;n++)e[n]=t,t+=q[n].width;return e[q.length]=t,e},[q]),Yt=J[J.length-1],Xt=t.useMemo(()=>q.map(e=>e.date.getTime()),[q]),Zt=t.useMemo(()=>q.map(e=>A(e.date,1,I).getTime()-e.date.getTime()),[q,I]),Y=t.useCallback(e=>{let t=q.length;if(t===0)return 0;let n=e.getTime(),r=0,i=t-1,a=0;for(;r<=i;){let e=r+i>>1;Xt[e]<=n?(a=e,r=e+1):i=e-1}let o=Zt[a]||864e5,s=(n-Xt[a])/o;return qt&&(s=Math.max(0,Math.min(s,1))),J[a]+s*q[a].width},[q,Xt,Zt,J,qt]),Qt=t.useCallback(e=>{let t=q.length;if(t===0)return new Date(K.start);let n=0,r=t-1,i=0;for(;n<=r;){let t=n+r>>1;J[t]<=e?(i=t,n=t+1):r=t-1}let a=q[i].width||1,o=(e-J[i])/a;return new Date(Xt[i]+o*(Zt[i]||864e5))},[q,Xt,Zt,J,K]),$t=t.useCallback(e=>{let t=X.current;Ve.current==null&&t&&t.clientWidth>0&&(Ve.current=Qt(t.scrollLeft)),Be.current=Ve.current,He.current=!0,ze(e),f?.(e)},[f,Qt]);t.useLayoutEffect(()=>{let e=Be.current;if(e==null)return;Be.current=null;let t=X.current;if(!t||t.clientWidth===0)return;let n=Math.max(0,t.scrollWidth-t.clientWidth),r=Math.max(0,Math.min(Math.round(Y(k(e,I))),n));t.scrollLeft!==r&&(t.scrollLeft=r)},[I,Y]);let en=t.useCallback((e,t)=>{let n=q.length;if(n===0||t===0)return new Date(e);let r=e.getTime(),i=0,a=n-1,o=0;for(;i<=a;){let e=i+a>>1;Xt[e]<=r?(o=e,i=e+1):a=e-1}let s=Math.min(n-1,Math.max(0,o+t)),c=r-Xt[o];return new Date(Xt[s]+c)},[q,Xt]),tn=t.useRef(null);tn.current=qt?en:null;let nn=t.useMemo(()=>{let e=[],t=I===`year`?`decade`:I===`month`||I===`quarter`?`year`:`month`,n=0;for(let r of q){let i=r.date.getFullYear(),a=Math.floor(i/10)*10,o=t===`decade`?String(a):t===`year`?String(i):`${i}-${r.date.getMonth()}`,s=e[e.length-1];s&&s.key===o?s.width+=r.width:e.push({key:o,label:t===`decade`?`${a}s`:t===`year`?String(i):r.date.toLocaleDateString(D,{month:`short`,year:`numeric`}),width:r.width,offset:n}),n+=r.width}return e},[q,I,D]),rn=t.useMemo(()=>(a??[]).map((e,t)=>{let n=e.date instanceof Date?e.date:new Date(e.date);return{index:t,label:e.label,color:e.color||`hsl(var(--primary))`,left:Math.round(Y(n)),valid:!isNaN(n.getTime())&&n>=K.start&&n<=K.end}}).filter(e=>e.valid),[a,K,Y]),an=t.useRef(null),on=t.useRef(null),sn=t.useRef(null),X=t.useRef(null);t.useEffect(()=>{let e=X.current;if(!e)return;let t=()=>{He.current=!1},n=new Set([`ArrowLeft`,`ArrowRight`,`ArrowUp`,`ArrowDown`,`PageUp`,`PageDown`,`Home`,`End`,` `,`Spacebar`]),r=e=>{n.has(e.key)&&t()};return e.addEventListener(`wheel`,t,{passive:!0}),e.addEventListener(`touchstart`,t,{passive:!0}),e.addEventListener(`pointerdown`,t,{passive:!0}),e.addEventListener(`keydown`,r),()=>{e.removeEventListener(`wheel`,t),e.removeEventListener(`touchstart`,t),e.removeEventListener(`pointerdown`,t),e.removeEventListener(`keydown`,r)}},[]);let[cn,ln]=t.useState(null),un=t.useRef([]),dn=t.useRef(null),[fn,pn]=t.useState({top:0,left:0}),[mn,hn]=t.useState({width:4e3,height:600}),gn=t.useCallback(()=>{let e=X.current;if(!e)return;let t=e.clientWidth||4e3,n=e.clientHeight||600;hn(e=>e.width===t&&e.height===n?e:{width:t,height:n})},[]);t.useLayoutEffect(()=>{gn();let e=X.current;if(!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(gn);return t.observe(e),()=>t.disconnect()},[gn]);let _n=t.useMemo(()=>me(J,fn.left-240,fn.left+mn.width+240),[J,fn.left,mn.width]),vn=t.useMemo(()=>{let e=nn.map(e=>e.offset);return e.push(Yt),e},[nn,Yt]),yn=t.useMemo(()=>me(vn,fn.left-240,fn.left+mn.width+240),[vn,fn.left,mn.width]),Z=t.useMemo(()=>({startIdx:Math.max(0,Math.floor(fn.top/F)-6),endIdx:Math.min(G.length,Math.ceil((fn.top+mn.height)/F)+6)}),[fn.top,mn.height,F,G.length]),bn=G.length*F,[xn,Sn]=t.useState(!1);t.useEffect(()=>{let e=()=>Sn(!!document.fullscreenElement);return document.addEventListener(`fullscreenchange`,e),()=>document.removeEventListener(`fullscreenchange`,e)},[]);let Cn=t.useCallback(()=>{let e=Ce.current;e&&(document.fullscreenElement?document.exitFullscreen?.():e.requestFullscreen?.())},[]),wn=t.useRef(null),Tn=t.useCallback(e=>{if(e.touches.length===2){let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY;wn.current={baseDistance:Math.max(1,Math.sqrt(t*t+n*n)),baseColumn:R}}},[R]),En=t.useCallback(e=>{if(e.touches.length!==2||!wn.current)return;let t=e.touches[0].clientX-e.touches[1].clientX,n=e.touches[0].clientY-e.touches[1].clientY,r=Math.max(1,Math.sqrt(t*t+n*n))/wn.current.baseDistance;Ie(Math.max(15,Math.min(120,Math.round(wn.current.baseColumn*r))))},[]),Dn=t.useCallback(()=>{wn.current=null},[]),Q=t.useMemo(()=>{let e=new Date;return e<K.start||e>K.end?null:Math.round(Y(e))},[K,Y]),On=t.useCallback(()=>{if(Q==null||!X.current)return;let e=Math.max(0,Q-X.current.clientWidth/2);X.current.scrollTo({left:e,behavior:`smooth`})},[Q]),kn=t.useRef(!1);t.useEffect(()=>{if(kn.current||e.length===0)return;let t=window.requestAnimationFrame(()=>{let t=X.current;if(!t||t.clientWidth===0)return;let n=Q;if(n==null){let t=new Date(Math.min(...e.map(e=>e.start.getTime())));n=Math.round(Y(t))}t.scrollLeft=Math.max(0,n-t.clientWidth/2),kn.current=!0});return()=>window.cancelAnimationFrame(t)},[e,Q,Y]);let An=t.useCallback((e,t=`left`)=>{let n=X.current;if(!n||e<K.start||e>K.end)return!1;let r=Math.round(Y(e)),i=t===`center`?r-n.clientWidth/2:r-24;return n.scrollTo({left:Math.max(0,i),behavior:`smooth`}),!0},[K,Y]),jn=t.useCallback((e,t,n)=>{let r=X.current;if(!r)return;let i=Y(e),a=Y(t),o=Math.max(0,r.scrollWidth-r.clientWidth),s=Math.min(96,r.clientWidth*.15),c=a-i<=r.clientWidth-s?(i+a)/2-r.clientWidth/2:i-s,l=Math.max(0,Math.min(c,o));un.current.forEach(e=>window.clearTimeout(e)),un.current=[],dn.current?.(),dn.current=null,ln(null);let u=()=>{if(n==null)return;let e=window.requestAnimationFrame(()=>{ln(n),un.current.push(window.setTimeout(()=>ln(e=>e===n?null:e),1500))});dn.current=()=>window.cancelAnimationFrame(e)},d=Math.abs(r.scrollLeft-l)>2;if(r.scrollTo({left:l,behavior:`smooth`}),!d){u();return}let f=`onscrollend`in r,p=!1,m=()=>{p||(p=!0,r.removeEventListener(`scrollend`,m),u())};r.addEventListener(`scrollend`,m),un.current.push(window.setTimeout(m,f?1500:500)),dn.current=()=>r.removeEventListener(`scrollend`,m)},[Y]);t.useEffect(()=>()=>{un.current.forEach(e=>window.clearTimeout(e)),dn.current?.()},[]);let Mn=t.useCallback(()=>An(k(new Date,`week`)),[An]),Nn=t.useCallback(()=>An(k(new Date,`month`)),[An]),Pn=e=>{let t=e.currentTarget;!He.current&&t.clientWidth>0&&(Ve.current=Qt(t.scrollLeft)),an.current&&(an.current.scrollLeft=t.scrollLeft),on.current&&on.current.scrollTop!==t.scrollTop&&(on.current.scrollTop=t.scrollTop),pn(e=>e.top===t.scrollTop&&e.left===t.scrollLeft?e:{top:t.scrollTop,left:t.scrollLeft}),gn()},Fn=e=>{let t=e.currentTarget,n=X.current;n&&n.scrollTop!==t.scrollTop&&(n.scrollTop=t.scrollTop),pn(e=>e.top===t.scrollTop?e:{...e,top:t.scrollTop})},In=(e,t)=>{let n=Y(e);return{left:n,width:Math.max(Y(t)-n,Je,3)}},Ln=B?.group?B.taskId:null,Rn=t.useMemo(()=>{if(Ln==null)return null;let e=new Set([String(Ln)]);for(let t of it(Ln))e.add(String(t.id));return e},[Ln,it]),zn=t.useMemo(()=>{if(!B||B.group)return null;let e=new Set,t=new Set,n=rt.get(String(B.taskId));for(;n&&n.parent!=null&&n.parent!==``;){let r=String(n.parent);if(t.has(r)||!rt.has(r))break;t.add(r),e.add(r),n=rt.get(r)}return e.size?e:null},[B,rt]),Bn=e=>{if(B){if(Rn?.has(String(e.task.id))){let t=ct(B).start.getTime()-B.originStart.getTime();return In(new Date(e.start.getTime()+t),new Date(e.end.getTime()+t))}if(!e.isSummary&&B.taskId===e.task.id){let e=ct(B);return In(e.start,e.end)}if(e.isSummary&&zn?.has(String(e.task.id))){let t=ct(B),n=String(B.taskId),r=null,i=null;for(let a of it(e.task.id)){if((nt.get(String(a.id))??[]).length!==0)continue;let e=String(a.id)===n?t.start:a.start,o=String(a.id)===n?t.end:a.end;(!r||e<r)&&(r=e),(!i||o>i)&&(i=o)}if(r&&i)return In(r,i)}}return In(e.start,e.end)},Vn=t.useMemo(()=>{let e=new Map;G.forEach((t,n)=>e.set(String(t.task.id),n));let t=[];return G.forEach(({task:n},r)=>{for(let i of n.dependencies??[]){let a=typeof i==`object`&&!!i,o=a?i.id:i;if(o==null||o===``)continue;let s=e.get(String(o));if(s==null||s===r)continue;let c=a?i.type:void 0,l=c===`ss`||c===`ff`||c===`sf`?c:`fs`;t.push({key:`${String(o)}->${String(n.id)}:${l}`,sourceId:o,targetId:n.id,type:l,sourceIndex:s,targetIndex:r})}}),t},[G]),Hn=Math.round(F*.2),Un=F-Hn*2,Wn=Math.max(Math.round(F*.4),12),Gn=Wn*Math.SQRT2/2,Kn=Un,qn=Hn,Jn=Math.max(3,Math.round(F*.13)),Yn=F-Jn-1,Xn=`rgba(100, 116, 139, 0.35)`,Zn=`rgba(100, 116, 139, 0.6)`,Qn=e=>{let t=G[e.sourceIndex],n=G[e.targetIndex];if(!t||!n)return null;let r=Bn(t),i=Bn(n),a=e=>e.isSummary?qn+Kn/2:F/2,o=e.sourceIndex*F+a(t),s=e.targetIndex*F+a(n),c=e.type===`fs`||e.type===`ff`,l=e.type===`ff`||e.type===`sf`,u=t.isMilestone?r.left+(c?Gn:-Gn):c?r.left+r.width:r.left,d=n.isMilestone?i.left+(l?Gn:-Gn):l?i.left+i.width:i.left,f=u+(c?10:-10),p=d+(l?10:-10),m=Math.round,h=[`M ${m(u)} ${m(o)}`,`L ${m(f)} ${m(o)}`];if(l?f>=p:f<=p)h.push(`L ${m(f)} ${m(s)}`,`L ${m(d)} ${m(s)}`);else{let t=s>=o?(e.sourceIndex+1)*F:e.sourceIndex*F;h.push(`L ${m(f)} ${m(t)}`,`L ${m(p)} ${m(t)}`,`L ${m(p)} ${m(s)}`,`L ${m(d)} ${m(s)}`)}return h.join(` `)},$n=B?.taskId??et,[er,tr]=t.useState(b),nr=t.useMemo(()=>er?ie(e,x):null,[er,e,x]),rr=t.useCallback(e=>nr?.criticalIds.has(String(e))??!1,[nr]),$=`#dc2626`,ir=t.useCallback(()=>{if(!N)return;let t=ae(e,x),n=[];for(let r of t){let t=e.find(e=>String(e.id)===r.id);t&&n.push({task:t,changes:{start:r.start,end:r.end}})}V(n)},[e,N,x,V]),ar=t.useCallback(()=>{if(typeof document>`u`||!e.length)return null;let t=e=>String(e).replace(/[&<>"]/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`})[e]),n=Math.max(L,200),r=Math.ceil(n+Yt),i=Math.ceil(36+G.length*F),a=nr?.criticalEdges??null,o=[];o.push(`<rect x="0" y="0" width="${r}" height="${i}" fill="#ffffff"/>`),o.push(`<rect x="0" y="0" width="${r}" height="36" fill="#f8fafc"/>`),o.push(`<g transform="translate(${n},0)" font-family="sans-serif" font-size="10" fill="#475569">`),nn.forEach(e=>{o.push(`<line x1="${e.offset.toFixed(1)}" y1="0" x2="${e.offset.toFixed(1)}" y2="36" stroke="#e2e8f0"/>`),o.push(`<text x="${(e.offset+e.width/2).toFixed(1)}" y="12" text-anchor="middle" font-weight="600">${t(e.label)}</text>`)}),q.forEach((e,n)=>{let r=J[n];o.push(`<line x1="${r.toFixed(1)}" y1="18" x2="${r.toFixed(1)}" y2="${i}" stroke="#eef2f7"/>`),o.push(`<text x="${(r+e.width/2).toFixed(1)}" y="30" text-anchor="middle" fill="#1f2937">${t(e.label)}</text>`)}),o.push(`</g>`),o.push(`<line x1="0" y1="18" x2="${r}" y2="18" stroke="#e2e8f0"/>`),o.push(`<line x1="0" y1="36" x2="${r}" y2="36" stroke="#cbd5e1"/>`),o.push(`<line x1="${n}" y1="0" x2="${n}" y2="${i}" stroke="#cbd5e1"/>`),o.push(`<g transform="translate(0,36)" font-family="sans-serif" font-size="11" fill="#1f2937">`),G.forEach((e,r)=>{let i=r*F;o.push(`<line x1="0" y1="${(i+F).toFixed(1)}" x2="${n}" y2="${(i+F).toFixed(1)}" stroke="#f1f5f9"/>`);let a=8+e.depth*14,s=Math.max(4,Math.floor((n-a)/6.5)),c=e.task.title.length>s?e.task.title.slice(0,s-1)+`…`:e.task.title,l=e.isSummary?` font-weight="600"`:``;o.push(`<text x="${a}" y="${(i+F/2+4).toFixed(1)}"${l}>${t(c)}</text>`)}),o.push(`</g>`),o.push(`<g transform="translate(${n},36)" font-family="sans-serif" font-size="9">`),G.forEach((e,t)=>{let n=t*F,{left:r,width:i}=In(e.start,e.end),a=rr(e.task.id),s=a?` stroke="${$}" stroke-width="2"`:``;if(ee&&e.task.baselineStart&&e.task.baselineEnd){let t=In(e.task.baselineStart,e.task.baselineEnd);o.push(`<rect x="${t.left.toFixed(1)}" y="${(n+Yn).toFixed(1)}" width="${Math.max(2,t.width).toFixed(1)}" height="${Jn}" rx="1" fill="${Xn}" stroke="${Zn}"/>`)}if(e.isMilestone){let t=r,i=n+F/2,s=Wn/2,c=a?$:e.task.color||`#3b82f6`;o.push(`<polygon points="${t},${i-s} ${t+s},${i} ${t},${i+s} ${t-s},${i}" fill="${c}"/>`)}else if(e.isSummary){let t=e.task.color||`#64748b`;o.push(`<rect x="${r.toFixed(1)}" y="${(n+qn).toFixed(1)}" width="${i.toFixed(1)}" height="${Kn}" rx="3" fill="${t}"${s}/>`);let a=i*Math.min(100,Math.max(0,e.progress))/100;o.push(`<rect x="${r.toFixed(1)}" y="${(n+qn).toFixed(1)}" width="${a.toFixed(1)}" height="${Kn}" rx="3" fill="rgba(0,0,0,0.2)"/>`)}else{let t=e.task.color||`#3b82f6`;o.push(`<rect x="${r.toFixed(1)}" y="${(n+Hn).toFixed(1)}" width="${i.toFixed(1)}" height="${Un}" rx="3" fill="${t}"${s}/>`);let a=i*Math.min(100,Math.max(0,e.progress))/100;o.push(`<rect x="${r.toFixed(1)}" y="${(n+Hn).toFixed(1)}" width="${a.toFixed(1)}" height="${Un}" rx="3" fill="rgba(0,0,0,0.18)"/>`),i>=24&&o.push(`<text x="${(r+i/2).toFixed(1)}" y="${(n+F/2+3).toFixed(1)}" text-anchor="middle" fill="#ffffff">${Math.round(e.progress)}%</text>`)}}),Vn.forEach(e=>{let t=Qn(e);if(!t)return;let n=a?.has(`${String(e.sourceId)}->${String(e.targetId)}`)??!1,r=n?$:`#94a3b8`;o.push(`<path d="${t}" fill="none" stroke="${r}" stroke-width="${n?2:1.5}"/>`)}),Q!=null&&o.push(`<line x1="${Q.toFixed(1)}" y1="0" x2="${Q.toFixed(1)}" y2="${G.length*F}" stroke="#ef4444" stroke-width="1.5"/>`);let s=G.length*F;return rn.forEach(e=>{let n=/var\(/.test(e.color)?`#6366f1`:e.color;if(o.push(`<line x1="${e.left.toFixed(1)}" y1="0" x2="${e.left.toFixed(1)}" y2="${s}" stroke="${t(n)}" stroke-width="1.5"/>`),e.label){let r=e.label.length*6+8;o.push(`<rect x="${(e.left-r/2).toFixed(1)}" y="0" width="${r}" height="14" rx="2" fill="${t(n)}"/>`),o.push(`<text x="${e.left.toFixed(1)}" y="10" text-anchor="middle" font-size="9" font-weight="600" fill="#ffffff">${t(e.label)}</text>`)}}),o.push(`</g>`),{svg:`<svg xmlns="http://www.w3.org/2000/svg" width="${r}" height="${i}" viewBox="0 0 ${r} ${i}">${o.join(``)}</svg>`,W:r,H:i}},[e,G,Vn,Qn,In,rr,nr,q,J,Yt,L,F,Hn,Un,qn,Kn,Wn,Q,I,ee,Yn,Jn,Xn,Zn,rn,nn]),or=t.useCallback(async()=>{let e=ar();if(!e)return;let t=await he(e.svg,e.W,e.H);t&&t.toBlob(e=>{e&&ge(e,`gantt-${I}.png`)},`image/png`)},[ar,I]),sr=t.useCallback(async()=>{let e=ar();if(!e)return;let t=await he(e.svg,e.W,e.H);t&&ge(_e(ve(t.toDataURL(`image/jpeg`,.92)),t.width,t.height),`gantt-${I}.pdf`)},[ar,I]),[cr,lr]=t.useState(!1),ur=t.useCallback(()=>{let e={viewMode:I,columnWidth:Fe,taskListCollapsed:Ue,taskListWidth:Le};ne&&xe(ne,e),re?.(e),lr(!0)},[I,Fe,Ue,Le,ne,re]);return t.useEffect(()=>{if(!cr)return;let e=setTimeout(()=>lr(!1),1500);return()=>clearTimeout(e)},[cr]),(0,u.jsxs)(`div`,{ref:Ce,className:(0,s.cn)(`flex flex-col h-full bg-background overflow-hidden min-w-0`,g),"data-readonly":M?`true`:void 0,"data-mobile-readonly":S&&Te?`true`:void 0,children:[(0,u.jsx)(`style`,{children:`
16
+ .gantt-resize-handle:hover { background-color: rgba(255, 255, 255, 0.4); }
17
+ .gantt-bar-hover:hover { filter: brightness(1.1); }
18
+ .gantt-locate-btn { opacity: 0; transition: opacity 0.15s ease; }
19
+ .group\\/task-row:hover .gantt-locate-btn { opacity: 0.6; }
20
+ .gantt-locate-btn:hover, .gantt-locate-btn:focus-visible { opacity: 1; }
21
+ /* 定位闪烁: blink the located bar 3× with a thick ring + colored glow so
22
+ it's hard to miss. The ring is an outline (not box-shadow) and the glow
23
+ is a drop-shadow *filter* — both stay clear of the critical-path bar's
24
+ inline box-shadow, which they'd otherwise clobber. */
25
+ @keyframes gantt-flash {
26
+ 0%, 25%, 50%, 100% {
27
+ outline-color: rgba(37, 99, 235, 0);
28
+ filter: drop-shadow(0 0 0 rgba(37, 99, 235, 0));
29
+ }
30
+ 12%, 37%, 62% {
31
+ outline-color: rgba(37, 99, 235, 1);
32
+ filter: drop-shadow(0 0 9px rgba(37, 99, 235, 0.9));
33
+ }
34
+ }
35
+ .gantt-flash {
36
+ outline: 3px solid transparent;
37
+ outline-offset: 3px;
38
+ border-radius: 2px;
39
+ animation: gantt-flash 1.5s ease-in-out;
40
+ }
41
+ @media (min-width: 640px) {
42
+ .gantt-sm-h50 { height: 50px; }
43
+ .gantt-sm-w20 { width: 80px; }
44
+ .gantt-sm-hidden { display: none; }
45
+ }
46
+ /* Persistent, grabbable timeline scrollbars. macOS (and iOS) default to
47
+ overlay scrollbars that collapse to 0px and auto-hide, so the
48
+ timeline's vertical scrollbar was nearly impossible to find. Defining
49
+ ::-webkit-scrollbar opts this pane into a classic, always-visible bar
50
+ regardless of the OS overlay preference. The thumb gets a min size so
51
+ that with thousands of virtualized rows (scrollHeight in the hundreds
52
+ of thousands of px) it never shrinks to an un-grabbable sliver. Scoped
53
+ to the gantt pane so the host app's own scrollbars are untouched, and
54
+ themed with neutral rgba (not theme utilities, which don't always
55
+ reach a consuming app) so it's visible on any background. */
56
+ /* Firefox (and any engine without ::-webkit-scrollbar) only: the
57
+ standard props. We must NOT set these unconditionally — modern Chrome
58
+ now honors scrollbar-width and, when it's present, IGNORES the
59
+ ::-webkit-scrollbar rule below, falling back to the 0px auto-hiding
60
+ overlay bar we're trying to replace. */
61
+ @supports not selector(::-webkit-scrollbar) {
62
+ [data-testid="gantt-timeline"] {
63
+ scrollbar-width: thin;
64
+ scrollbar-color: rgba(130,130,130,0.55) transparent;
65
+ }
66
+ }
67
+ [data-testid="gantt-timeline"]::-webkit-scrollbar {
68
+ width: 14px;
69
+ height: 14px;
70
+ }
71
+ [data-testid="gantt-timeline"]::-webkit-scrollbar-track {
72
+ background: transparent;
73
+ }
74
+ [data-testid="gantt-timeline"]::-webkit-scrollbar-thumb {
75
+ background-color: rgba(130,130,130,0.55);
76
+ border-radius: 8px;
77
+ border: 3px solid transparent;
78
+ background-clip: padding-box;
79
+ min-height: 40px;
80
+ min-width: 40px;
81
+ }
82
+ [data-testid="gantt-timeline"]::-webkit-scrollbar-thumb:hover {
83
+ background-color: rgba(110,110,110,0.85);
84
+ }
85
+ [data-testid="gantt-timeline"]::-webkit-scrollbar-corner {
86
+ background: transparent;
87
+ }
88
+ /* The task-list pane scrolls in lockstep with the timeline, so its own
89
+ vertical scrollbar (butted against the divider) was a confusing second
90
+ bar. Hide it — the pane stays wheel/drag-scrollable and synced. */
91
+ .gantt-task-list::-webkit-scrollbar { width: 0; height: 0; }
92
+ .gantt-task-list { scrollbar-width: none; }
93
+ `}),(0,u.jsxs)(`div`,{className:`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2 p-2 border-b bg-card`,children:[(0,u.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":E(`gantt.toolbar.prevPeriod`),children:(0,u.jsx)(l.ChevronLeft,{className:`h-4 w-4`})}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,"aria-label":E(`gantt.toolbar.nextPeriod`),children:(0,u.jsx)(l.ChevronRight,{className:`h-4 w-4`})}),(0,u.jsx)(`span`,{className:`font-semibold text-xs sm:text-sm`,children:K.start.toLocaleDateString(D,{month:`long`,year:`numeric`})}),M&&(0,u.jsxs)(`span`,{className:`inline-flex items-center gap-1 rounded-full border bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground`,"data-testid":`gantt-readonly-badge`,title:E(`gantt.readOnlyHint`),children:[(0,u.jsx)(l.Lock,{className:`h-3 w-3`}),E(`gantt.readOnly`)]})]}),(0,u.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,u.jsx)(`div`,{className:`flex bg-muted rounded-md p-1`,role:`group`,"aria-label":E(`gantt.toolbar.viewMode`),children:O.map(e=>(0,u.jsx)(s.Button,{variant:`ghost`,size:`sm`,className:(0,s.cn)(`h-6 px-1.5 sm:px-2 text-xs`,I===e&&`bg-background shadow-sm hover:bg-background`),onClick:()=>$t(e),"aria-pressed":I===e,"data-testid":`gantt-view-mode-${e}`,children:E(`gantt.viewMode.${e}`)},e))}),(0,u.jsxs)(`div`,{className:`flex bg-muted rounded-md p-1`,children:[(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>{if(R>15)Ie(Math.max(15,R-10));else{let e=O.indexOf(I);e<O.length-1&&($t(O[e+1]),Ie(Me))}},"aria-label":E(`gantt.toolbar.zoomOut`),children:(0,u.jsx)(l.ZoomOut,{className:`h-3 w-3`})}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-6 w-6`,onClick:()=>{if(R<120)Ie(Math.min(120,R+10));else{let e=O.indexOf(I);e>0&&($t(O[e-1]),Ie(Me))}},"aria-label":E(`gantt.toolbar.zoomIn`),children:(0,u.jsx)(l.ZoomIn,{className:`h-3 w-3`})})]}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>We(e=>!e),"aria-label":E(Ue?`gantt.toolbar.showTaskList`:`gantt.toolbar.hideTaskList`),"aria-pressed":Ue,"data-testid":`gantt-toggle-task-list`,children:Ue?(0,u.jsx)(l.PanelLeft,{className:`h-4 w-4`}):(0,u.jsx)(l.PanelLeftClose,{className:`h-4 w-4`})}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`sm`,className:`h-8 px-2 text-xs`,onClick:On,disabled:Q==null,"aria-label":E(`gantt.toolbar.jumpToToday`),"data-testid":`gantt-jump-today`,children:E(`gantt.toolbar.today`)}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`sm`,className:`h-8 px-2 text-xs`,onClick:Mn,"aria-label":E(`gantt.toolbar.thisWeek`),"data-testid":`gantt-jump-week`,children:E(`gantt.toolbar.thisWeek`)}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`sm`,className:`h-8 px-2 text-xs`,onClick:Nn,"aria-label":E(`gantt.toolbar.thisMonth`),"data-testid":`gantt-jump-month`,children:E(`gantt.toolbar.thisMonth`)}),N?(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:yt,disabled:!xt,"aria-label":E(`gantt.toolbar.undo`),"data-testid":`gantt-undo`,children:(0,u.jsx)(l.Undo2,{className:`h-4 w-4`})}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:bt,disabled:!St,"aria-label":E(`gantt.toolbar.redo`),"data-testid":`gantt-redo`,children:(0,u.jsx)(l.Redo2,{className:`h-4 w-4`})})]}):null,(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:()=>tr(e=>!e),"aria-label":E(`gantt.toolbar.criticalPath`),"aria-pressed":er,"data-testid":`gantt-critical-path`,style:er?{color:$}:void 0,children:(0,u.jsx)(l.Activity,{className:`h-4 w-4`})}),Ae&&N?(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:ir,"aria-label":E(`gantt.toolbar.autoSchedule`),"data-testid":`gantt-auto-schedule`,children:(0,u.jsx)(l.Wand2,{className:`h-4 w-4`})}):null,(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:or,"aria-label":E(`gantt.toolbar.exportPng`),"data-testid":`gantt-export-png`,children:(0,u.jsx)(l.Download,{className:`h-4 w-4`})}),(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:sr,"aria-label":E(`gantt.toolbar.exportPdf`),"data-testid":`gantt-export-pdf`,children:(0,u.jsx)(l.FileDown,{className:`h-4 w-4`})}),re||ne?(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:ur,"aria-label":E(`gantt.toolbar.saveLayout`),"aria-pressed":cr,"data-testid":`gantt-save-layout`,style:cr?{color:$}:void 0,children:(0,u.jsx)(l.Save,{className:`h-4 w-4`})}):null,(0,u.jsx)(s.Button,{variant:`ghost`,size:`icon`,className:`h-8 w-8`,onClick:Cn,"aria-label":E(xn?`gantt.toolbar.exitFullscreen`:`gantt.toolbar.enterFullscreen`),"aria-pressed":xn,"data-testid":`gantt-fullscreen`,children:xn?(0,u.jsx)(l.Minimize2,{className:`h-4 w-4`}):(0,u.jsx)(l.Maximize2,{className:`h-4 w-4`})})]})]}),(0,u.jsxs)(`div`,{className:`relative flex flex-col flex-1 overflow-hidden outline-none focus-visible:ring-1 focus-visible:ring-ring`,tabIndex:0,onKeyDown:Kt,"data-testid":`gantt-body`,children:[!Ue&&L>0&&(0,u.jsx)(`div`,{className:`absolute top-0 bottom-0 z-30 group/splitter`,style:{left:L-3,width:7,cursor:`col-resize`},"data-testid":`gantt-list-resize`,role:`separator`,"aria-orientation":`vertical`,onPointerDown:e=>{if(e.button!==0)return;e.preventDefault();let t=e.clientX,n=L,r=Math.max(160,j-200),i=e=>{Re(Math.max(160,Math.min(n+(e.clientX-t),r)))},a=()=>{window.removeEventListener(`pointermove`,i),window.removeEventListener(`pointerup`,a),window.removeEventListener(`pointercancel`,a),document.body.style.cursor=``};document.body.style.cursor=`col-resize`,window.addEventListener(`pointermove`,i),window.addEventListener(`pointerup`,a),window.addEventListener(`pointercancel`,a)},onDoubleClick:()=>Re(null),children:(0,u.jsx)(`div`,{className:`absolute inset-y-0 left-1/2 -translate-x-1/2 w-px bg-border group-hover/splitter:w-[3px] group-hover/splitter:bg-primary transition-all`})}),(0,u.jsxs)(`div`,{className:`flex border-b bg-muted/30 shrink-0 h-10 gantt-sm-h50`,children:[(0,u.jsxs)(`div`,{className:`flex items-center font-medium text-xs text-muted-foreground px-2 sm:px-4 border-r bg-card z-20 shadow-sm`,style:{width:L,minWidth:L},children:[(0,u.jsx)(`div`,{className:`flex-1 truncate`,children:E(`gantt.column.taskName`)}),Ye&&(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`div`,{className:`w-16 gantt-sm-w20 text-right`,children:E(`gantt.column.start`)}),(0,u.jsx)(`div`,{className:`w-16 gantt-sm-w20 text-right`,children:E(`gantt.column.end`)})]})]}),(0,u.jsx)(`div`,{className:`flex-1 overflow-hidden`,ref:an,children:(0,u.jsxs)(`div`,{className:`flex flex-col h-full`,style:{width:Yt},children:[(0,u.jsx)(`div`,{className:`relative border-b`,style:{height:`45%`},"data-testid":`gantt-header-groups`,children:nn.slice(yn.start,yn.end).map(e=>(0,u.jsx)(`div`,{className:`absolute top-0 bottom-0 flex items-center justify-center border-r text-[10px] font-medium text-muted-foreground overflow-hidden`,style:{left:e.offset,width:e.width},children:(0,u.jsx)(`span`,{className:`truncate px-1`,children:e.label})},e.key))}),(0,u.jsx)(`div`,{className:`relative flex-1`,"data-testid":`gantt-header-units`,children:q.slice(_n.start,_n.end).map((e,t)=>{let n=_n.start+t;return(0,u.jsxs)(`div`,{className:(0,s.cn)(`absolute top-0 bottom-0 flex items-center justify-center gap-1 border-r text-xs text-muted-foreground overflow-hidden`,e.isWeekend&&`bg-muted/50`),style:{left:J[n],width:e.width},children:[(0,u.jsx)(`span`,{className:`font-medium text-foreground truncate`,children:e.label}),e.sublabel&&R>=32&&(0,u.jsx)(`span`,{className:`text-[10px] opacity-70`,children:e.sublabel})]},n)})})]})})]}),(0,u.jsxs)(`div`,{className:`flex flex-1 overflow-hidden`,children:[(0,u.jsxs)(`div`,{className:`gantt-task-list overflow-y-auto overflow-x-hidden border-r bg-card z-10 shadow-sm`,ref:on,onScroll:Fn,style:{width:L,minWidth:L},role:`tree`,"aria-label":E(`gantt.aria.taskList`),children:[Z.startIdx>0&&(0,u.jsx)(`div`,{style:{height:Z.startIdx*F},"aria-hidden":`true`}),G.slice(Z.startIdx,Z.endIdx).map(e=>{let t=e.task,n=ke&&Xe===t.id,r=Ht.has(String(t.id)),i=Lt!=null&&String(Lt)===String(t.id);return(0,u.jsxs)(`div`,{className:(0,s.cn)(`group/task-row relative flex items-center border-b px-2 sm:px-4 hover:bg-accent/50 cursor-pointer transition-colors`,i&&`bg-accent/50`),style:{height:F,touchAction:`manipulation`},role:`treeitem`,"aria-level":e.depth+1,"aria-selected":i,"aria-expanded":e.hasChildren?!r:void 0,draggable:!!Oe&&!n&&!t.locked,onDragStart:Oe?e=>{e.dataTransfer.setData(`text/plain`,String(t.id)),e.dataTransfer.effectAllowed=`move`}:void 0,onDragOver:Oe?e=>{e.preventDefault(),e.dataTransfer.dropEffect=`move`}:void 0,onDrop:Oe?e=>{e.preventDefault();let n=e.dataTransfer.getData(`text/plain`);if(!n||n===String(t.id))return;let r=rt.get(n);r&&String(r.parent??``)===String(t.parent??``)&&Oe(r,t)}:void 0,onContextMenu:e=>Bt(t,e),onClick:()=>{Rt(t.id),n||o?.(t)},onDoubleClick:()=>{ke&&N&&!e.isSummary&&!t.locked&&(Ze(t.id),$e({title:t.title,start:t.start.toLocaleDateString(`en-CA`),end:t.end.toLocaleDateString(`en-CA`),progress:String(t.progress)}))},children:[(0,u.jsxs)(`div`,{className:`flex-1 truncate font-medium text-xs sm:text-sm flex items-center gap-2`,style:e.depth>0?{paddingLeft:e.depth*14}:void 0,children:[e.hasChildren?(0,u.jsx)(`button`,{type:`button`,className:`h-4 w-4 shrink-0 flex items-center justify-center text-muted-foreground hover:text-foreground`,style:{marginLeft:-4},onClick:e=>{e.stopPropagation(),Wt(t.id)},"aria-expanded":!r,"aria-label":E(r?`gantt.row.expand`:`gantt.row.collapse`),"data-testid":`gantt-row-toggle-${t.id}`,children:r?(0,u.jsx)(l.ChevronRight,{className:`h-3.5 w-3.5`}):(0,u.jsx)(l.ChevronDown,{className:`h-3.5 w-3.5`})}):(0,u.jsx)(`span`,{className:`w-3 shrink-0`,style:{marginLeft:-4},"aria-hidden":`true`}),(0,u.jsx)(`div`,{className:`w-2 h-2 rounded-full shrink-0`,style:{backgroundColor:t.color||`#3b82f6`}}),n?(0,u.jsx)(`input`,{className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:Qe.title||``,onChange:e=>$e(t=>({...t,title:e.target.value})),onKeyDown:e=>{e.key===`Enter`?(V([{task:t,changes:{title:Qe.title,start:new Date(Qe.start),end:new Date(Qe.end),progress:Number(Qe.progress)||0}}]),Ze(null)):e.key===`Escape`&&Ze(null)},onClick:e=>e.stopPropagation(),autoFocus:!0}):(0,u.jsxs)(`span`,{className:`flex flex-col min-w-0`,children:[(0,u.jsx)(`span`,{className:(0,s.cn)(`truncate`,e.isSummary&&`font-semibold`),children:t.title}),(0,u.jsxs)(`span`,{className:`text-[10px] text-muted-foreground gantt-sm-hidden`,children:[e.start.toLocaleDateString(D,{month:`numeric`,day:`numeric`}),` → `,e.end.toLocaleDateString(D,{month:`numeric`,day:`numeric`})]})]})]}),(0,u.jsx)(`div`,{className:`w-16 gantt-sm-w20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!Ye,style:Ye?void 0:{display:`none`},children:n?(0,u.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:Qe.start||``,onChange:e=>$e(t=>({...t,start:e.target.value})),onClick:e=>e.stopPropagation()}):e.start.toLocaleDateString(D,{month:`numeric`,day:`numeric`})}),(0,u.jsx)(`div`,{className:`w-16 gantt-sm-w20 text-right text-xs text-muted-foreground hidden sm:block`,hidden:!Ye,style:Ye?void 0:{display:`none`},children:n?(0,u.jsx)(`input`,{type:`date`,className:`border rounded px-1 py-0.5 text-xs w-full bg-background`,value:Qe.end||``,onChange:e=>$e(t=>({...t,end:e.target.value})),onClick:e=>e.stopPropagation()}):e.end.toLocaleDateString(D,{month:`numeric`,day:`numeric`})}),!n&&(0,u.jsx)(`button`,{type:`button`,title:E(`gantt.row.locate`),"aria-label":E(`gantt.row.locate`),className:`gantt-locate-btn hidden sm:block absolute top-1/2 -translate-y-1/2`,style:{right:1},onClick:t=>{t.stopPropagation(),jn(e.start,e.end,e.task.id)},children:(0,u.jsx)(l.Crosshair,{className:`w-3 h-3`})})]},t.id)}),Z.endIdx<G.length&&(0,u.jsx)(`div`,{style:{height:(G.length-Z.endIdx)*F},"aria-hidden":`true`})]}),(0,u.jsx)(`div`,{className:`flex-1 overflow-auto bg-background/50 relative [-webkit-overflow-scrolling:touch]`,ref:e=>{sn.current=e,X.current=e},onScroll:Pn,onTouchStart:Tn,onTouchMove:En,onTouchEnd:Dn,"data-testid":`gantt-timeline`,children:(0,u.jsxs)(`div`,{className:`relative`,style:{width:Yt},children:[Q!=null&&(0,u.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px z-20 pointer-events-none`,style:{left:Q,backgroundColor:`rgba(239, 68, 68, 0.8)`},"data-testid":`gantt-today-marker`,"aria-label":E(`gantt.toolbar.today`),children:(0,u.jsx)(`div`,{className:`absolute -translate-x-1/2 left-0 text-[10px] font-semibold text-white rounded-sm px-1 py-0.5 whitespace-nowrap z-30`,style:{top:2,backgroundColor:`#ef4444`},children:E(`gantt.toolbar.today`)})}),rn.map(e=>(0,u.jsx)(`div`,{className:`absolute top-0 bottom-0 w-px z-20 pointer-events-none`,style:{left:e.left,backgroundColor:e.color},"data-testid":`gantt-marker-${e.index}`,"aria-label":e.label,children:e.label&&(0,u.jsx)(`div`,{className:`absolute -translate-x-1/2 left-0 text-[10px] font-semibold text-white rounded-sm px-1 py-0.5 whitespace-nowrap z-30`,style:{top:2,backgroundColor:e.color},children:e.label})},e.index)),(0,u.jsxs)(`div`,{className:`relative`,ref:Dt,children:[(0,u.jsx)(`div`,{className:`absolute inset-0 pointer-events-none`,style:{zIndex:0},children:q.slice(_n.start,_n.end).map((e,t)=>{let n=_n.start+t;return(0,u.jsx)(`div`,{className:`absolute top-0 bottom-0 border-r`,style:{left:J[n],width:e.width,backgroundColor:e.isWeekend?`hsl(var(--muted) / 0.4)`:void 0}},n)})}),Z.startIdx>0&&(0,u.jsx)(`div`,{style:{height:Z.startIdx*F},"aria-hidden":`true`}),G.slice(Z.startIdx,Z.endIdx).map(e=>{let n=e.task,r=rr(n.id),i=In(e.start,e.end),a=ee&&n.baselineStart&&n.baselineEnd?In(n.baselineStart,n.baselineEnd):null,c=a?(0,u.jsx)(`div`,{className:`absolute pointer-events-none rounded-[1px]`,style:{left:a.left,width:Math.max(2,a.width),top:Yn,height:Jn,backgroundColor:Xn,border:`1px solid ${Zn}`},"data-testid":`gantt-baseline-${n.id}`,"aria-hidden":`true`}):null,l=B?.taskId===n.id,d=Rn?.has(String(n.id))??!1,f=zn?.has(String(n.id))??!1,p=l||d||f?Bn(e):i,m=!!n.locked,h=!!N&&!e.isSummary&&!m,g=H!=null&&H.targetId!=null&&String(H.targetId)===String(n.id)&&String(H.sourceId)!==String(n.id),_=H?e=>{let t=e.currentTarget.getBoundingClientRect(),r=t.width>0&&e.clientX-t.left>t.width/2?`end`:`start`;Ot(e=>e&&String(e.sourceId)!==String(n.id)?{...e,targetId:n.id,targetEnd:r}:e)}:void 0,v=H?e=>{e.target===e.currentTarget&&Ot(e=>e&&{...e,targetId:null,targetEnd:null})}:void 0,y=Math.max(1,Math.round((e.end.getTime()-e.start.getTime())/pe)),b=et===n.id&&!B&&!wt&&!H?(0,u.jsxs)(`div`,{className:`absolute z-30 pointer-events-none rounded-md border bg-popover text-popover-foreground px-2.5 py-1.5 text-xs shadow-md whitespace-nowrap`,style:{left:Math.max(p.left+8,4),top:F-8},role:`tooltip`,"data-testid":`gantt-tooltip-${n.id}`,children:[(0,u.jsx)(`div`,{className:`font-semibold`,children:n.title}),n.fields&&n.fields.length>0?(0,u.jsx)(`div`,{style:{display:`grid`,gridTemplateColumns:`auto 1fr`,columnGap:10,rowGap:2,marginTop:4},children:n.fields.map((e,n)=>(0,u.jsxs)(t.Fragment,{children:[(0,u.jsx)(`span`,{className:`text-muted-foreground`,children:e.label}),(0,u.jsx)(`span`,{style:{fontWeight:500},children:e.value})]},n))}):(0,u.jsxs)(`div`,{className:`text-muted-foreground`,children:[e.start.toLocaleDateString(D,{month:`short`,day:`numeric`}),` → `,e.end.toLocaleDateString(D,{month:`short`,day:`numeric`}),` · `,y,E(`gantt.tooltip.days`),` · `,Math.round(e.progress),`%`]})]}):null;if(n.type===`group`)return(0,u.jsx)(`div`,{className:`relative border-b hover:bg-accent/50`,style:{height:F},onPointerMove:v,children:b},n.id);if(e.isSummary){let t=n.color||`#0d9488`;return(0,u.jsxs)(`div`,{className:`relative border-b hover:bg-accent/50`,style:{height:F},onPointerMove:v,children:[c,(0,u.jsxs)(`div`,{className:(0,s.cn)(`gantt-bar-hover absolute rounded-sm border shadow-sm flex items-center px-2 select-none`,N?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,l&&`ring-2 ring-primary z-10`,cn===n.id&&`gantt-flash z-10`),style:{left:p.left,width:p.width,top:qn,height:Kn,backgroundColor:t,borderColor:r?$:`hsl(var(--primary-foreground) / 0.2)`,boxShadow:r?`0 0 0 2px ${$}`:void 0},"data-critical":r?`true`:void 0,"data-testid":`gantt-summary-bar-${n.id}`,"data-progress":Math.round(e.progress),onMouseEnter:()=>tt(n.id),onMouseLeave:()=>tt(e=>e===n.id?null:e),onPointerDown:t=>{t.button===0&&Ct(n,`move`,t,{group:!0,originStart:e.start,originEnd:e.end})},onClick:()=>{st.current||o?.(n)},onContextMenu:e=>Bt(n,e),children:[(0,u.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 pointer-events-none`,style:{width:`${Math.round(e.progress)}%`,backgroundColor:`rgba(0, 0, 0, 0.2)`,borderTopLeftRadius:`var(--radius-sm)`,borderBottomLeftRadius:`var(--radius-sm)`}}),(0,u.jsx)(`span`,{className:`relative text-[10px] text-white font-medium truncate pointer-events-none`,children:n.title})]}),l&&B&&(0,u.jsxs)(`div`,{className:`absolute z-30 pointer-events-none rounded border bg-popover text-popover-foreground px-1.5 py-0.5 text-[10px] shadow whitespace-nowrap`,style:{left:Math.max(p.left,4),top:qn+Kn+2},"data-testid":`gantt-summary-drag-chip-${n.id}`,children:[ct(B).start.toLocaleDateString(D,{month:`numeric`,day:`numeric`}),` → `,ct(B).end.toLocaleDateString(D,{month:`numeric`,day:`numeric`})]}),b]},n.id)}if(e.isMilestone){let e=Wn;return(0,u.jsxs)(`div`,{className:`relative border-b hover:bg-accent/50`,style:{height:F},onPointerMove:v,children:[c,(0,u.jsx)(`div`,{className:(0,s.cn)(`gantt-bar-hover absolute rotate-45 rounded-[2px] border shadow-sm select-none`,h?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,l&&`ring-2 ring-primary z-10`,g&&`ring-2 ring-primary`,cn===n.id&&`gantt-flash z-10`),style:{left:p.left-e/2,top:(F-e)/2,width:e,height:e,backgroundColor:r?$:n.color||`#3b82f6`,borderColor:r?$:`hsl(var(--primary-foreground) / 0.2)`,boxShadow:r?`0 0 0 2px ${$}`:void 0},"data-critical":r?`true`:void 0,"data-testid":`gantt-milestone-${n.id}`,onMouseEnter:()=>tt(n.id),onMouseLeave:()=>tt(e=>e===n.id?null:e),onClick:()=>{st.current||o?.(n)},onContextMenu:e=>Bt(n,e),onPointerMove:_,onPointerDown:h?e=>{e.button===0&&Ct(n,`move`,e)}:void 0}),b]},n.id)}let x=wt&&wt.taskId===n.id?wt.value:n.progress;return(0,u.jsxs)(`div`,{className:`relative border-b hover:bg-accent/50`,style:{height:F},onPointerMove:v,onMouseEnter:()=>tt(n.id),onMouseLeave:()=>tt(e=>e===n.id?null:e),children:[l&&(0,u.jsx)(`div`,{className:`absolute rounded-sm border border-dashed pointer-events-none`,style:{left:i.left,width:i.width,top:Hn,height:Un,opacity:.35,borderColor:`hsl(var(--primary) / 0.6)`},"aria-hidden":`true`}),c,(0,u.jsxs)(`div`,{className:(0,s.cn)(`gantt-bar-hover absolute rounded-sm bg-primary border shadow-sm flex items-center px-2 group select-none`,h?`cursor-grab active:cursor-grabbing`:`cursor-pointer`,l&&`ring-2 ring-primary z-10`,g&&`ring-2 ring-primary`,cn===n.id&&`gantt-flash z-10`),style:{left:p.left,width:p.width,top:Hn,height:Un,backgroundColor:n.color||`#3b82f6`,borderColor:r?$:`hsl(var(--primary-foreground) / 0.2)`,boxShadow:r?`0 0 0 2px ${$}`:void 0},"data-critical":r?`true`:void 0,"data-testid":`gantt-task-bar-${n.id}`,onClick:()=>{st.current||o?.(n)},onContextMenu:e=>Bt(n,e),onPointerMove:_,onPointerDown:h?e=>{e.button===0&&Ct(n,`move`,e)}:void 0,children:[h&&p.width>=14&&(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`div`,{className:`gantt-resize-handle absolute left-0 top-0 bottom-0`,style:{width:6,cursor:`ew-resize`},"data-testid":`gantt-task-resize-left-${n.id}`,onPointerDown:e=>{e.button===0&&Ct(n,`resize-left`,e)},onClick:e=>e.stopPropagation()}),(0,u.jsx)(`div`,{className:`gantt-resize-handle absolute right-0 top-0 bottom-0`,style:{width:6,cursor:`ew-resize`},"data-testid":`gantt-task-resize-right-${n.id}`,onPointerDown:e=>{e.button===0&&Ct(n,`resize-right`,e)},onClick:e=>e.stopPropagation()})]}),x>0&&(0,u.jsx)(`div`,{className:`absolute left-0 top-0 bottom-0 pointer-events-none`,style:{width:`${x}%`,backgroundColor:`rgba(0, 0, 0, 0.2)`,borderTopLeftRadius:`var(--radius-sm)`,borderBottomLeftRadius:`var(--radius-sm)`}}),h&&p.width>=30&&(0,u.jsx)(`div`,{className:(0,s.cn)(`absolute bottom-0 h-1/2 w-4 -translate-x-1/2 cursor-col-resize flex items-end justify-center pb-px`,wt?.taskId===n.id?`opacity-100`:`opacity-0 group-hover:opacity-100 transition-opacity`),style:{left:`${x}%`},"data-testid":`gantt-progress-handle-${n.id}`,onPointerDown:e=>{e.button===0&&(e.stopPropagation(),e.preventDefault(),Tt({taskId:n.id,originClientX:e.clientX,originProgress:n.progress,barWidth:p.width,value:n.progress}))},onClick:e=>e.stopPropagation(),children:(0,u.jsx)(`div`,{style:{width:0,height:0,borderLeft:`5px solid transparent`,borderRight:`5px solid transparent`,borderBottom:`7px solid #fff`,filter:`drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35))`}})}),P&&!m&&[`start`,`end`].map(e=>{let t=H!=null&&String(H.sourceId)===String(n.id)&&H.sourceEnd===e,r=t||et===n.id,i=r&&H==null;return(0,u.jsx)(`div`,{className:`absolute top-1/2 -translate-y-1/2 z-20 flex items-center transition-opacity`,style:{[e===`start`?`left`:`right`]:-28,height:24,width:30,cursor:`crosshair`,opacity:+!!r,pointerEvents:i?`auto`:`none`,justifyContent:e===`start`?`flex-start`:`flex-end`,paddingLeft:e===`start`?4:0,paddingRight:e===`end`?4:0},"data-testid":`gantt-link-dot-${e}-${n.id}`,onPointerDown:t=>{if(t.button!==0)return;t.stopPropagation(),t.preventDefault();let r=Dt.current?.getBoundingClientRect();Ot({sourceId:n.id,sourceEnd:e,x:r?t.clientX-r.left:0,y:r?t.clientY-r.top:0,targetId:null,targetEnd:null})},onClick:e=>e.stopPropagation(),children:(0,u.jsx)(`div`,{className:`rounded-full`,style:{height:12,width:12,backgroundColor:`hsl(var(--background))`,border:`2px solid hsl(var(--primary))`,boxShadow:t?`0 0 0 3px hsl(var(--primary) / 0.25)`:`0 1px 2px rgba(0,0,0,0.25)`}})},e)}),(0,u.jsx)(`span`,{className:`relative text-[10px] text-white font-medium truncate pointer-events-none group-hover:opacity-0 transition-opacity`,children:n.title}),(0,u.jsx)(`span`,{className:`absolute inset-0 flex items-center px-2 text-[10px] text-white font-medium truncate opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none`,children:l?`${ct(B).start.toLocaleDateString(D,{month:`numeric`,day:`numeric`})} → ${ct(B).end.toLocaleDateString(D,{month:`numeric`,day:`numeric`})}`:`${Math.round(x)}%`})]}),b]},n.id)}),Z.endIdx<G.length&&(0,u.jsx)(`div`,{style:{height:(G.length-Z.endIdx)*F},"aria-hidden":`true`}),(Vn.length>0||H)&&(0,u.jsxs)(`svg`,{className:`absolute top-0 left-0 pointer-events-none z-10`,width:Yt,height:bn,"data-testid":`gantt-links`,"aria-hidden":`true`,children:[(0,u.jsxs)(`defs`,{children:[(0,u.jsx)(`marker`,{id:`gantt-link-arrow`,viewBox:`0 0 8 8`,refX:`7`,refY:`4`,markerWidth:`6`,markerHeight:`6`,orient:`auto`,children:(0,u.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 z`,fill:`hsl(var(--muted-foreground))`})}),(0,u.jsx)(`marker`,{id:`gantt-link-arrow-active`,viewBox:`0 0 8 8`,refX:`7`,refY:`4`,markerWidth:`6`,markerHeight:`6`,orient:`auto`,children:(0,u.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 z`,fill:`hsl(var(--primary))`})}),(0,u.jsx)(`marker`,{id:`gantt-link-arrow-critical`,viewBox:`0 0 8 8`,refX:`7`,refY:`4`,markerWidth:`6`,markerHeight:`6`,orient:`auto`,children:(0,u.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 z`,fill:$})})]}),Vn.map(e=>{let n=Math.min(e.sourceIndex,e.targetIndex);if(Math.max(e.sourceIndex,e.targetIndex)<Z.startIdx-6||n>Z.endIdx+6)return null;let r=Qn(e);if(!r)return null;let i=$n!=null&&(String(e.sourceId)===String($n)||String(e.targetId)===String($n)),a=nr?.criticalEdges.has(`${String(e.sourceId)}->${String(e.targetId)}`)??!1,o=a?`gantt-link-arrow-critical`:i?`gantt-link-arrow-active`:`gantt-link-arrow`,s=!!(De||P);return(0,u.jsxs)(t.Fragment,{children:[(0,u.jsx)(`path`,{d:r,fill:`none`,stroke:a?$:i?`hsl(var(--primary))`:`hsl(var(--muted-foreground))`,strokeOpacity:a||i?1:.7,strokeWidth:a||i?2:1.5,markerEnd:`url(#${o})`,"data-testid":`gantt-link-${e.sourceId}-${e.targetId}`,"data-link-type":e.type,"data-active":i?`true`:`false`,"data-critical":a?`true`:void 0}),s&&(0,u.jsx)(`path`,{d:r,fill:`none`,stroke:`transparent`,strokeWidth:10,style:{pointerEvents:`stroke`,cursor:`context-menu`},"data-testid":`gantt-link-hit-${e.sourceId}-${e.targetId}`,onContextMenu:t=>Vt(e.sourceId,e.targetId,e.type,t)})]},e.key)}),H&&(()=>{let e=G.findIndex(e=>String(e.task.id)===String(H.sourceId));if(e<0)return null;let t=Bn(G[e]),n=G[e].isMilestone?t.left+(H.sourceEnd===`start`?-Gn:Gn):H.sourceEnd===`start`?t.left:t.left+t.width,r=e*F+F/2;return(0,u.jsx)(`path`,{d:`M ${Math.round(n)} ${Math.round(r)} L ${Math.round(H.x)} ${Math.round(H.y)}`,fill:`none`,stroke:`hsl(var(--primary))`,strokeWidth:1.5,strokeDasharray:`4 3`,"data-testid":`gantt-link-draft`})})()]}),H&&(()=>{let t=e.find(e=>String(e.id)===String(H.sourceId));if(!t)return null;let n=H.targetId==null?null:e.find(e=>String(e.id)===String(H.targetId)),r=e=>E(`gantt.linkEnd.${e}`),i=n?`${t.title} (${r(H.sourceEnd)}) → ${n.title} (${r(H.targetEnd??`start`)})`:`${t.title} (${r(H.sourceEnd)})`;return(0,u.jsx)(`div`,{className:`absolute z-30 pointer-events-none rounded-md border bg-popover text-popover-foreground px-2 py-1 text-[11px] font-medium shadow-md whitespace-nowrap`,style:{left:H.x+12,top:H.y+12},"data-testid":`gantt-link-draft-hint`,children:i})})()]})]})})]})]}),At&&(()=>{let t=e.find(e=>String(e.id)===String(At.taskId));if(!t)return null;let n=G.find(e=>String(e.task.id)===String(At.taskId)),r=`w-full text-left px-3 py-1.5 hover:bg-accent focus:bg-accent outline-none`;return(0,u.jsxs)(`div`,{ref:Mt,className:`fixed z-50 min-w-[160px] rounded-md border bg-popover text-popover-foreground shadow-md py-1 text-sm`,style:{left:At.x,top:At.y},role:`menu`,"data-testid":`gantt-context-menu`,children:[o&&(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:r,"data-testid":`gantt-context-menu-view`,onClick:()=>{jt(null),o(t)},children:E(`gantt.menu.view`)}),ke&&N&&n&&!n.isSummary&&!t.locked&&(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:r,"data-testid":`gantt-context-menu-edit`,onClick:()=>{jt(null),Ze(t.id),$e({title:t.title,start:t.start.toLocaleDateString(`en-CA`),end:t.end.toLocaleDateString(`en-CA`),progress:String(t.progress)})},children:E(`gantt.menu.edit`)}),P&&n&&!n.isMilestone&&!t.locked&&(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:r,"data-testid":`gantt-context-menu-add-predecessor`,onClick:()=>{let e=At;jt(null),Ft({x:e.x,y:e.y,taskId:t.id,relation:`pred`})},children:E(`gantt.menu.addPredecessor`)}),(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:r,"data-testid":`gantt-context-menu-add-successor`,onClick:()=>{let e=At;jt(null),Ft({x:e.x,y:e.y,taskId:t.id,relation:`succ`})},children:E(`gantt.menu.addSuccessor`)})]}),Ee&&!t.locked&&(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:(0,s.cn)(r,`text-destructive`),"data-testid":`gantt-context-menu-delete`,onClick:()=>{jt(null),Ee(t)},children:E(`gantt.menu.delete`)})]})})(),U&&(()=>{let t=e.find(e=>String(e.id)===String(U.sourceId)),n=e.find(e=>String(e.id)===String(U.targetId));if(!t||!n)return null;let r=`w-full text-left px-3 py-1.5 hover:bg-accent focus:bg-accent outline-none`;return(0,u.jsxs)(`div`,{ref:Pt,className:`fixed z-50 min-w-[180px] rounded-md border bg-popover text-popover-foreground shadow-md py-1 text-sm`,style:{left:U.x,top:U.y},role:`menu`,"data-testid":`gantt-link-context-menu`,children:[(0,u.jsxs)(`div`,{className:`px-3 py-1 text-xs text-muted-foreground truncate`,children:[t.title,` → `,n.title]}),P&&[`fs`,`ss`,`ff`,`sf`].map(e=>(0,u.jsxs)(`button`,{type:`button`,role:`menuitemradio`,"aria-checked":U.type===e,className:(0,s.cn)(r,U.type===e&&`font-semibold`),"data-testid":`gantt-link-menu-type-${e}`,onClick:()=>{Nt(null),e!==U.type&&P(t,n,e)},children:[U.type===e?`✓ `:`\xA0\xA0`,E(`gantt.linkType.${e}`)]},e)),De&&(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`div`,{className:`my-1 border-t`}),(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:(0,s.cn)(r,`text-destructive`),"data-testid":`gantt-link-menu-remove`,onClick:()=>{Nt(null),De(t,n)},children:E(`gantt.menu.removeDependency`)})]})]})})(),W&&P&&(()=>{let t=e.find(e=>String(e.id)===String(W.taskId));if(!t)return null;let n=new Set(Vn.map(e=>`${String(e.sourceId)}->${String(e.targetId)}`)),r=e.filter(e=>{if(String(e.id)===String(t.id)||e.type===`summary`)return!1;let r=W.relation===`pred`?`${String(e.id)}->${String(t.id)}`:`${String(t.id)}->${String(e.id)}`;return!n.has(r)});return(0,u.jsxs)(`div`,{ref:It,className:`fixed z-50 min-w-[200px] max-h-[280px] overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md py-1 text-sm`,style:{left:W.x,top:W.y},role:`menu`,"data-testid":`gantt-dep-picker`,children:[(0,u.jsx)(`div`,{className:`px-3 py-1 text-xs text-muted-foreground`,children:W.relation===`pred`?E(`gantt.menu.addPredecessor`):E(`gantt.menu.addSuccessor`)}),r.length===0?(0,u.jsx)(`div`,{className:`px-3 py-1.5 text-muted-foreground`,children:E(`gantt.menu.noCandidates`)}):r.map(e=>(0,u.jsx)(`button`,{type:`button`,role:`menuitem`,className:`w-full text-left px-3 py-1.5 hover:bg-accent focus:bg-accent outline-none truncate`,"data-testid":`gantt-dep-picker-option-${e.id}`,onClick:()=>{Ft(null),W.relation===`pred`?P(e,t,`fs`):P(t,e,`fs`)},children:e.title},String(e.id)))]})})(),mt&&(0,u.jsx)(`div`,{className:`fixed inset-0 z-[60] flex items-center justify-center bg-black/30`,"data-testid":`gantt-conflict-overlay`,onClick:()=>ht(null),children:(0,u.jsxs)(`div`,{className:`min-w-[280px] max-w-[360px] rounded-lg border bg-popover text-popover-foreground shadow-lg p-4`,role:`alertdialog`,"aria-modal":`true`,"data-testid":`gantt-conflict-dialog`,onClick:e=>e.stopPropagation(),children:[(0,u.jsx)(`div`,{className:`text-sm font-semibold mb-1`,"data-testid":`gantt-conflict-title`,children:E(`gantt.conflict.title`)}),(0,u.jsx)(`div`,{className:`text-sm text-muted-foreground mb-3`,children:E(`gantt.conflict.body`).replace(`{count}`,String(mt.length))}),(0,u.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[(0,u.jsx)(`button`,{type:`button`,className:`px-3 py-1.5 text-sm rounded-md border hover:bg-accent outline-none`,"data-testid":`gantt-conflict-cancel`,onClick:()=>ht(null),children:E(`gantt.conflict.cancel`)}),(0,u.jsx)(`button`,{type:`button`,className:`px-3 py-1.5 text-sm rounded-md bg-primary text-primary-foreground hover:opacity-90 outline-none`,"data-testid":`gantt-conflict-confirm`,onClick:_t,children:E(`gantt.conflict.confirm`)})]})]})})]})}function Ce(e,t,n,r){return t.getTime()===e.getTime()?e.getTime()>=n.getTime()&&e.getTime()<r.getTime():e.getTime()<r.getTime()&&t.getTime()>n.getTime()}function we(e,t,n){let{assignee:r,effort:i,capacity:a=1,unassignedLabel:o=`Unassigned`}=n,s=e=>typeof a==`function`?a(e):a,c=e=>{let t=i?i(e):1;return Number.isFinite(t)&&t>0?t:0},l=new Map;for(let t of e){let e=r(t),n=e?String(e.key):`__unassigned__`,i=e?e.label:o,a=l.get(n);a||(a={key:n,label:i,items:[]},l.set(n,a)),a.items.push(t)}let u=[];for(let e of l.values()){let n=s(e.key),r=0,i=0,a=t.map(t=>{let a=0;for(let n of e.items)Ce(n.start,n.end,t.start,t.end)&&(a+=c(n));a>r&&(r=a);let o=a>n+1e-9;return o&&i++,{load:a,capacity:n,overloaded:o}});u.push({key:e.key,label:e.label,capacity:n,cells:a,peak:r,overloadedCount:i})}return u}var j={day:26,week:56,month:76,quarter:88,year:104},Te=48,M=34,N=180;function Ee(e,t,n){return t===`day`?String(e.getDate()):t===`week`?e.toLocaleDateString(n,{month:`numeric`,day:`numeric`}):t===`month`?e.toLocaleDateString(n,{month:`short`}):t===`year`?String(e.getFullYear()):`Q${Math.floor(e.getMonth()/3)+1}`}function P({tasks:e,assignee:n,effort:r,capacity:i=1,viewMode:a=`day`,unassignedLabel:o=`Unassigned`,className:s}){let{t:c,language:l}=se(),d=l||void 0,f=j[a],p=t.useMemo(()=>{if(!e.length)return[];let t=new Date(Math.min(...e.map(e=>e.start.getTime()))),n=new Date(Math.max(...e.map(e=>e.end.getTime()))),r=k(t,a),i=A(k(n,a),1,a),o=[],s=0;for(;r<i&&s++<4e3;){let e=A(r,1,a);o.push({date:new Date(r),col:{start:new Date(r),end:new Date(e)},label:Ee(r,a,d)}),r=e}return o},[e,a,d]),m=t.useMemo(()=>we(e,p.map(e=>e.col),{assignee:n,effort:r,capacity:i,unassignedLabel:o}),[e,p,n,r,i,o]),h=t.useMemo(()=>{let e=0;for(let t of m)e=Math.max(e,t.peak,t.capacity);return e||1},[m]),g=p.length*f;return e.length?(0,u.jsx)(`div`,{className:s,"data-testid":`resource-workload`,style:{display:`flex`,flexDirection:`column`,height:`100%`,overflow:`auto`},children:(0,u.jsxs)(`div`,{style:{display:`flex`,minWidth:N+g},children:[(0,u.jsxs)(`div`,{style:{width:N,flexShrink:0},children:[(0,u.jsx)(`div`,{style:{height:28,display:`flex`,alignItems:`center`,padding:`0 12px`,fontSize:12,fontWeight:600,borderBottom:`1px solid hsl(var(--border))`},children:c(`gantt.resource.header`)}),m.map(e=>(0,u.jsxs)(`div`,{"data-testid":`resource-row-${e.key}`,style:{height:Te,display:`flex`,flexDirection:`column`,justifyContent:`center`,padding:`0 12px`,borderBottom:`1px solid hsl(var(--border) / 0.5)`},children:[(0,u.jsx)(`span`,{style:{fontSize:13,fontWeight:500,whiteSpace:`nowrap`,overflow:`hidden`,textOverflow:`ellipsis`},children:e.label}),(0,u.jsxs)(`span`,{"data-testid":`resource-peak-${e.key}`,"data-overloaded":e.overloadedCount>0?`true`:void 0,style:{fontSize:10,color:e.overloadedCount>0?`hsl(var(--destructive))`:`hsl(var(--muted-foreground))`},children:[c(`gantt.resource.peak`),`: `,Math.round(e.peak*100)/100,` / `,e.capacity,e.overloadedCount>0?` · ${e.overloadedCount} ${c(`gantt.resource.over`)}`:``]})]},e.key))]}),(0,u.jsxs)(`div`,{style:{flex:1},children:[(0,u.jsx)(`div`,{style:{display:`flex`,height:28,borderBottom:`1px solid hsl(var(--border))`},children:p.map((e,t)=>(0,u.jsx)(`div`,{style:{width:f,flexShrink:0,textAlign:`center`,fontSize:10,color:`hsl(var(--muted-foreground))`,borderLeft:`1px solid hsl(var(--border) / 0.4)`,display:`flex`,alignItems:`center`,justifyContent:`center`},children:e.label},t))}),m.map(e=>{let t=M*(1-Math.min(e.capacity/h,1));return(0,u.jsxs)(`div`,{style:{position:`relative`,display:`flex`,height:Te,borderBottom:`1px solid hsl(var(--border) / 0.5)`},children:[(0,u.jsx)(`div`,{"aria-hidden":`true`,style:{position:`absolute`,left:0,right:0,top:(Te-M)/2+t,borderTop:`1px dashed hsl(var(--muted-foreground) / 0.6)`,pointerEvents:`none`,zIndex:1}}),e.cells.map((t,n)=>{let r=Math.max(t.load>0?2:0,M*Math.min(t.load/h,1));return(0,u.jsx)(`div`,{"data-testid":`resource-cell-${e.key}-${n}`,"data-load":t.load,"data-overloaded":t.overloaded?`true`:void 0,title:`${p[n]?.date.toLocaleDateString(d)} — ${Math.round(t.load*100)/100} / ${t.capacity}`,style:{width:f,flexShrink:0,position:`relative`,borderLeft:`1px solid hsl(var(--border) / 0.4)`,display:`flex`,alignItems:`flex-end`,justifyContent:`center`,paddingBottom:(Te-M)/2},children:t.load>0&&(0,u.jsx)(`div`,{style:{width:f-6,height:r,borderRadius:2,backgroundColor:t.overloaded?`hsl(var(--destructive))`:`hsl(var(--primary))`,opacity:t.overloaded?.9:.75}})},n)})]},e.key)})]})]})}):(0,u.jsx)(`div`,{className:s,"data-testid":`resource-workload`,children:(0,u.jsx)(`div`,{className:`flex items-center justify-center h-40 text-sm text-muted-foreground`,children:c(`gantt.resource.empty`)})})}var De={display:`flex`,flexWrap:`wrap`,alignItems:`center`,gap:8,padding:`8px 12px`,borderBottom:`1px solid hsl(var(--border))`,background:`hsl(var(--background))`,fontSize:13},Oe={display:`inline-flex`,alignItems:`center`,gap:6,height:30,padding:`0 10px`,borderRadius:6,border:`1px solid hsl(var(--border))`,background:`hsl(var(--background))`,color:`hsl(var(--foreground))`,cursor:`pointer`,whiteSpace:`nowrap`,lineHeight:`28px`},ke={position:`absolute`,top:`calc(100% + 4px)`,left:0,zIndex:50,minWidth:200,maxHeight:320,overflowY:`auto`,padding:4,borderRadius:8,border:`1px solid hsl(var(--border))`,background:`hsl(var(--popover, var(--background)))`,color:`hsl(var(--popover-foreground, var(--foreground)))`,boxShadow:`0 8px 24px rgba(0,0,0,0.18)`},Ae={display:`flex`,alignItems:`center`,gap:8,padding:`6px 8px`,borderRadius:6,cursor:`pointer`,userSelect:`none`};function je({checked:e}){return(0,u.jsx)(`span`,{"aria-hidden":!0,style:{display:`inline-flex`,alignItems:`center`,justifyContent:`center`,width:15,height:15,flex:`0 0 auto`,borderRadius:3,border:`1px solid ${e?`hsl(var(--primary))`:`hsl(var(--border))`}`,background:e?`hsl(var(--primary))`:`transparent`,color:`hsl(var(--primary-foreground, var(--background)))`,fontSize:11,lineHeight:1},children:e?`✓`:``})}function F({filter:e,selected:n,onChange:r,labels:i}){let[a,o]=(0,t.useState)(!1),s=(0,t.useRef)(null);(0,t.useEffect)(()=>{if(!a)return;let e=e=>{s.current&&!s.current.contains(e.target)&&o(!1)},t=e=>{e.key===`Escape`&&o(!1)};return document.addEventListener(`pointerdown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`pointerdown`,e),document.removeEventListener(`keydown`,t)}},[a]);let c=new Set(n),l=n.length,d=e.options.length>0&&l===e.options.length,f=t=>{let n=new Set(c);n.has(t)?n.delete(t):n.add(t),n.size===e.options.length?r([]):r([...n])},p=()=>{r(l>0?[]:e.options.map(e=>e.value))},m=l===0?e.label:l===1?`${e.label}: ${e.options.find(e=>e.value===n[0])?.label??n[0]}`:`${e.label} · ${l}`;return(0,u.jsxs)(`div`,{ref:s,style:{position:`relative`},"data-testid":`quick-filter-${e.field}`,children:[(0,u.jsxs)(`button`,{type:`button`,style:{...Oe,borderColor:l>0?`hsl(var(--primary))`:`hsl(var(--border))`,color:l>0?`hsl(var(--primary))`:`hsl(var(--foreground))`},"aria-haspopup":`listbox`,"aria-expanded":a,"data-testid":`quick-filter-trigger-${e.field}`,onClick:()=>o(e=>!e),children:[(0,u.jsx)(`span`,{children:m}),(0,u.jsx)(`span`,{"aria-hidden":!0,style:{fontSize:10,opacity:.7},children:`▾`})]}),a&&(0,u.jsx)(`div`,{role:`listbox`,style:ke,"data-testid":`quick-filter-panel-${e.field}`,children:e.options.length===0?(0,u.jsx)(`div`,{style:{...Ae,cursor:`default`,opacity:.6},children:i.empty}):(0,u.jsxs)(u.Fragment,{children:[(0,u.jsxs)(`div`,{role:`option`,"aria-selected":d,style:{...Ae,fontWeight:600},"data-testid":`quick-filter-all-${e.field}`,onClick:()=>p(),children:[(0,u.jsx)(je,{checked:d}),(0,u.jsx)(`span`,{children:i.all})]}),(0,u.jsx)(`div`,{style:{height:1,background:`hsl(var(--border))`,margin:`2px 0`}}),e.options.map(t=>{let n=c.has(t.value);return(0,u.jsxs)(`div`,{role:`option`,"aria-selected":n,style:{...Ae,background:n?`hsl(var(--accent, var(--muted)))`:`transparent`},"data-testid":`quick-filter-option-${e.field}-${t.value}`,onClick:()=>f(t.value),children:[(0,u.jsx)(je,{checked:n}),(0,u.jsx)(`span`,{children:t.label})]},t.value)})]})})]})}var Me=({filters:e,value:t,onChange:n,onClear:r,resultCount:i,totalCount:a,labels:o,className:s})=>{if(!e.length)return null;let c=o?.all??`All`,l=o?.empty??`No options`,d=o?.clear??`Clear`,f=e.some(e=>(t[e.field]?.length??0)>0);return(0,u.jsxs)(`div`,{style:De,className:s,"data-testid":`quick-filter-bar`,children:[e.map(e=>(0,u.jsx)(F,{filter:e,selected:t[e.field]??[],onChange:t=>n(e.field,t),labels:{all:c,empty:l}},e.field)),f&&(0,u.jsx)(`button`,{type:`button`,style:{...Oe,height:28,color:`hsl(var(--muted-foreground))`},"data-testid":`quick-filter-clear`,onClick:r,children:d}),o?.resultSummary&&i!=null&&a!=null&&(0,u.jsx)(`span`,{"data-testid":`quick-filter-summary`,style:{marginLeft:`auto`,color:`hsl(var(--muted-foreground))`},children:o.resultSummary(i,a)})]})};function Ne(e){if(e==null)return;let t=String(e).toLowerCase().trim();if(t===`milestone`)return`milestone`;if(t===`group`||t===`folder`)return`group`;if(t===`summary`||t===`project`||t===`phase`)return`summary`;if(t===`task`)return`task`}var Pe={fs:`fs`,ss:`ss`,ff:`ff`,sf:`sf`,finish_to_start:`fs`,start_to_start:`ss`,finish_to_finish:`ff`,start_to_finish:`sf`,end_to_start:`fs`,end_to_end:`ff`,start_to_end:`sf`};function Fe(e){if(e==null||e===``)return[];if(typeof e==`string`)return e.split(`,`).map(e=>e.trim()).filter(Boolean);if(typeof e==`number`)return[e];if(!Array.isArray(e))return[];let t=[];for(let n of e)if(!(n==null||n===``))if(typeof n==`object`){let e=n.id??n._id??n.task??n.target;if(e==null||e===``)continue;let r=Pe[String(n.type??``).toLowerCase().replace(/-/g,`_`)];t.push(r?{id:e,type:r}:{id:e})}else t.push(n);return t}function Ie(e){return e.data?e.data:e.staticData?{provider:`value`,items:e.staticData}:e.objectName?{provider:`object`,object:e.objectName}:null}function Le(e){if(e){if(typeof e==`string`){let t=e.split(` `),n=t[0],r=t[1]?.toLowerCase()===`desc`?`desc`:`asc`;return{[n]:r}}if(Array.isArray(e))return e.reduce((e,t)=>(t.field&&t.order&&(e[t.field]=t.order),e),{})}}function Re(e){let t=null;if(e.startDateField&&e.endDateField)return t={startDateField:e.startDateField,endDateField:e.endDateField,titleField:e.titleField||`name`,progressField:e.progressField,dependenciesField:e.dependenciesField||e.dependencyField,colorField:e.colorField,parentField:e.parentField,typeField:e.typeField,lockField:e.lockField,defaultCollapsedDepth:e.defaultCollapsedDepth,tooltipFields:e.tooltipFields,baselineStartField:e.baselineStartField,baselineEndField:e.baselineEndField,groupByField:e.groupByField,resourceView:e.resourceView,assigneeField:e.assigneeField,effortField:e.effortField,capacity:e.capacity,quickFilters:e.quickFilters,autoZoomToFilter:e.autoZoomToFilter},t;if(e.gantt&&(t=e.gantt),t){let e=i.GanttConfigSchema.safeParse(t);return e.success||console.warn(`[ObjectGantt] Invalid gantt configuration:`,e.error.format()),t}return null}var I=({schema:e,dataSource:i,className:l,onTaskClick:d,onRowClick:f,...p})=>{let[m,h]=(0,t.useState)([]),[g,_]=(0,t.useState)(!0),[v,y]=(0,t.useState)(null),[b,x]=(0,t.useState)(null),{currency:ee}=(0,a.useLocalization)(),te=Ie(e),S=(0,t.useMemo)(()=>te,[JSON.stringify(te)]),C=Re(e),w=S?.provider===`value`;(0,t.useEffect)(()=>{(async()=>{try{if(_(!0),p.data&&Array.isArray(p.data)){h(p.data),_(!1);return}if(w&&S?.provider===`value`){h(S.items),_(!1);return}if(!i||typeof i.find!=`function`)throw Error(`DataSource required for object/api providers`);if(S?.provider===`object`){let t=S.object,r=(0,n.buildExpandFields)(b?.fields);h((0,n.extractRecords)(await i.find(t,{$filter:e.filter,$orderby:Le(e.sort),...r.length>0?{$expand:r}:{}})))}else S?.provider===`api`&&(console.warn(`API provider not yet implemented for ObjectGantt`),h([]));_(!1)}catch(e){y(e),_(!1)}})()},[S,i,w,e.filter,e.sort,b]),(0,t.useEffect)(()=>{!w&&i&&(async()=>{try{if(!i)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t)return;x(await i.getObjectSchema(t))}catch(e){console.error(`Failed to fetch object schema:`,e)}})()},[e.objectName,i,w,S]);let T=(0,t.useMemo)(()=>{if(!C||!m.length)return[];let{startDateField:e,endDateField:t,titleField:n,progressField:r,dependenciesField:i,colorField:o,parentField:s,typeField:l,lockField:u,tooltipFields:d,baselineStartField:f,baselineEndField:p}=C,h=b?.fields??{},g=(e,t)=>{if(!t)return;let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r},_=e=>{let t=[g(e,n),e?.name,e?.title,e?.subject,e?.label,e?.account?.name,e?.opportunity?.name,e?.contact&&[e.contact.first_name,e.contact.last_name].filter(Boolean).join(` `),e?.id,e?._id];for(let e of t)if(e!=null&&String(e).trim()!==``)return String(e);return`Untitled`},v=(e,t)=>{if(t)return t;let n=h[e]??h[e.split(`.`)[0]];return n?.label?n.label:(0,c.humanizeLabel)(e)},y=(e,t)=>{if(e==null||e===``)return`—`;let n=h[t]??h[t.split(`.`)[0]],r=n?.type,i=n?.options;if(Array.isArray(i)&&i.length){let t=i.find(t=>String(t.value)===String(e));if(t)return t.label}switch(r){case`date`:return(0,c.formatDate)(e);case`datetime`:return(0,c.formatDateTime)(e);case`number`:case`integer`:case`float`:case`decimal`:return(0,c.formatNumber)(Number(e));case`currency`:return(0,c.formatCurrency)(Number(e),(0,a.resolveFieldCurrency)(n,ee));case`percent`:return(0,c.formatPercent)(Number(e));case`boolean`:case`checkbox`:return e?`Yes`:`No`;default:if(Array.isArray(e)){let t=e.map(e=>{if(e==null)return``;if(typeof e==`object`){let t=e;return String(t.name??t.label??t.title??t.id??``)}return String(e)}).filter(Boolean);return t.length?t.join(`, `):`—`}if(typeof e==`object`){let t=e;return String(t.name??t.label??t.title??t.id??`—`)}return String(e)}},x=e=>{if(!d||!d.length)return;let t=[];for(let n of d){let r=typeof n==`string`?n:n?.field;if(!r)continue;let i=typeof n==`object`?n.label:void 0;t.push({label:v(r,i),value:y(g(e,r),r)})}return t.length?t:void 0};return m.map((n,a)=>{let d=n[e],m=n[t],h=f?n[f]:void 0,g=p?n[p]:void 0,v=h?new Date(h):void 0,y=g?new Date(g):void 0,b=_(n),ee=r?n[r]:0,te=i?n[i]:[],S=o?n[o]:void 0;if(!S){let e=n.status??n.state??n.priority??n.severity;if(e!=null&&e!==``){let t=(0,c.getSemanticColorName)(void 0,e);t&&(S=(0,c.getSemanticHex)(t))}}return{id:n.id||n._id||`task-${a}`,title:b,start:d?new Date(d):new Date,end:m?new Date(m):new Date,progress:Math.min(100,Math.max(0,ee||0)),dependencies:Fe(te),parent:s?n[s]??null:void 0,type:l?Ne(n[l]):void 0,locked:u?!!n[u]:void 0,color:S,baselineStart:v&&!isNaN(v.getTime())?v:void 0,baselineEnd:y&&!isNaN(y.getTime())?y:void 0,fields:x(n),data:n}}).filter(e=>!isNaN(e.start.getTime())&&!isNaN(e.end.getTime()))},[m,C,b]),ne=(0,t.useMemo)(()=>{let e=C?.groupByField;if(!e)return;let t=b?.fields??{},n=(e,t)=>{if(!t)return;let n=e;for(let e of t.split(`.`)){if(n==null)return;n=n[e]}return n},r=n=>{let r=(t[e]??t[e.split(`.`)[0]])?.options;if(Array.isArray(r)&&r.length){let e=r.find(e=>String(e.value)===String(n));if(e)return e.label}if(typeof n==`object`&&n){let e=n;return String(e.name??e.label??e.title??e.id??n)}return String(n)};return t=>{let i=n(t.data,e);return i==null||i===``?null:{key:typeof i==`object`&&i?String(i.id??i._id??r(i)):i,label:r(i)}}},[C?.groupByField,b]),re=(0,t.useMemo)(()=>{let e=C?.assigneeField;if(!e)return;let t=b?.fields??{},n=(e,t)=>{if(!t)return;let n=e;for(let e of t.split(`.`)){if(n==null)return;n=n[e]}return n},r=n=>{let r=(t[e]??t[e.split(`.`)[0]])?.options;if(Array.isArray(r)&&r.length){let e=r.find(e=>String(e.value)===String(n));if(e)return e.label}if(typeof n==`object`&&n){let e=n;return String(e.name??e.label??e.title??e.id??n)}return String(n)};return t=>{let i=n(t.data,e);return i==null||i===``?null:{key:typeof i==`object`&&i?String(i.id??i._id??r(i)):i,label:r(i)}}},[C?.assigneeField,b]),E=(0,t.useMemo)(()=>{let e=C?.effortField;if(e)return t=>{let n=t.data?.[e],r=Number(n);return Number.isFinite(r)&&r>0?r:1}},[C?.effortField]),ie=(0,t.useMemo)(()=>{let t=e.skipWeekends,n=e.holidays;if(!(!t&&(!n||n.length===0)))return{skipWeekends:!!t,holidays:n&&n.length?new Set(n):void 0}},[e]),ae=(0,t.useCallback)((e,t)=>{if(!e||!t)return null;let n=e;for(let e of t.split(`.`)){if(n==null)return null;n=n[e]}if(n==null||n===``)return null;if(typeof n==`object`){let e=n;return String(e.id??e._id??e.value??e.name??``)}return String(n)},[]),oe=C?.quickFilters,[D,se]=(0,t.useState)({});(0,t.useEffect)(()=>{if(!oe?.length||!i||typeof i.find!=`function`)return;let e=b?.fields??{},t=!1;return(async()=>{let r={};for(let t of oe){if(t.options)continue;let a=e[t.field]??e[t.field.split(`.`)[0]],o=a?.type;if(o!==`lookup`&&o!==`master_detail`)continue;let s=a?.reference_to??a?.referenceTo;if(s)try{let e=(0,n.extractRecords)(await i.find(s,{$top:1e3}));r[t.field]=e.map(e=>({value:String(e.id??e._id??e.value??``),label:String(e.name??e.label??e.title??e.id??e._id??``)}))}catch(e){console.warn(`[ObjectGantt] Failed to load quick-filter options for "${t.field}":`,e)}}t||se(e=>({...e,...r}))})(),()=>{t=!0}},[JSON.stringify(oe),i,b]);let ce=(0,t.useMemo)(()=>{if(!oe?.length)return[];let e=b?.fields??{};return oe.map(t=>{let n=e[t.field]??e[t.field.split(`.`)[0]],r=t.label??n?.label??(0,c.humanizeLabel)(t.field),i=[];if(t.options?.length)i=t.options.map(e=>typeof e==`object`?{value:String(e.value),label:String(e.label??e.value)}:{value:String(e),label:String(e)});else if(Array.isArray(n?.options)&&n.options.length)i=n.options.map(e=>({value:String(e.value??e),label:String(e.label??e.value??e)}));else if(D[t.field]?.length)i=D[t.field];else{let e=new Map;for(let n of m){let r=ae(n,t.field);if(r!=null&&!e.has(r)){let i=n;for(let e of t.field.split(`.`))i=i?.[e];let a=i&&typeof i==`object`?String(i.name??i.label??i.title??r):r;e.set(r,a)}}i=[...e.entries()].map(([e,t])=>({value:e,label:t}))}return{field:t.field,label:r,options:i}})},[oe,b,D,m,ae]),[le,ue]=(0,t.useState)({}),de=(0,t.useCallback)((e,t)=>{ue(n=>({...n,[e]:t}))},[]),O=(0,t.useCallback)(()=>ue({}),[]),fe=(0,t.useMemo)(()=>{let e=Object.entries(le).filter(([,e])=>e.length>0);return e.length?T.filter(t=>e.every(([e,n])=>{let r=ae(t.data,e);return r!=null&&n.includes(r)})):T},[T,le,ae]),pe=(0,t.useMemo)(()=>{if(C?.autoZoomToFilter!==!1||!T.length)return null;let e=T[0].start.getTime(),t=T[0].end.getTime();for(let n of T)e=Math.min(e,n.start.getTime()),t=Math.max(t,n.end.getTime());return{start:new Date(e),end:new Date(t)}},[T,C?.autoZoomToFilter]),k=e.navigation??{mode:`drawer`,width:`min(960px, 60vw)`},me=k.mode===`drawer`||k.mode===`modal`||k.mode===`split`||k.mode===`popover`,A=(0,r.useNavigationOverlay)({navigation:k,objectName:e.objectName,onRowClick:me?void 0:f}),he=(0,t.useCallback)(async(t,n)=>{if(!C)return;let r=S?.provider===`object`?S.object:e.objectName;if(!r||!i||typeof i.update!=`function`)return;let{startDateField:a,endDateField:o,titleField:s,progressField:c}=C,l={};if(n.start instanceof Date&&(l[a]=n.start.toISOString()),n.end instanceof Date&&(l[o]=n.end.toISOString()),typeof n.title==`string`&&s&&(l[s]=n.title),typeof n.progress==`number`&&c&&(l[c]=n.progress),Object.keys(l).length===0)return;let u=t.data?.id??t.data?._id??t.id;if(u==null)return;let d=m;h(e=>e.map(e=>String(e.id??e._id)===String(u)?{...e,...l}:e));try{await i.update(r,String(u),l)}catch(e){console.error(`[ObjectGantt] Failed to persist task update:`,e),h(d)}},[C,S,i,e.objectName,m]),ge=(e,t)=>{let n=t.some(e=>typeof e==`object`&&e.type&&e.type!==`fs`);return!n&&typeof e==`string`?t.map(e=>String(typeof e==`object`?e.id:e)).join(`,`):n?t.map(e=>typeof e==`object`?e.type&&e.type!==`fs`?{id:e.id,type:e.type}:e.id:e):t.map(e=>typeof e==`object`?e.id:e)},_e=(0,t.useCallback)(async(t,n,r)=>{let a=C?.dependenciesField;if(!a)return;let o=S?.provider===`object`?S.object:e.objectName;if(!o||!i||typeof i.update!=`function`)return;let s=ge(n,r),c=m;h(e=>e.map(e=>String(e.id??e._id)===String(t)?{...e,[a]:s}:e));try{await i.update(o,String(t),{[a]:s})}catch(e){console.error(`[ObjectGantt] Failed to persist dependency:`,e),h(c)}},[C,S,i,e.objectName,m]),ve=(0,t.useCallback)(async(e,t,n=`fs`)=>{let r=e.data?.id??e.data?._id??e.id,i=t.data?.id??t.data?._id??t.id;if(r==null||i==null)return;let a=C?.dependenciesField;if(!a)return;let o=m.find(e=>String(e.id??e._id)===String(i))?.[a],s=Fe(o),c=e=>String(typeof e==`object`?e.id:e),l=s.find(e=>c(e)===String(r)),u=l&&typeof l==`object`?l.type??`fs`:`fs`;if(l&&u===n)return;let d=n===`fs`?r:{id:r,type:n};await _e(i,o,l?s.map(e=>c(e)===String(r)?d:e):[...s,d])},[C,m,_e]),ye=(0,t.useCallback)(async(e,t)=>{let n=e.data?.id??e.data?._id??e.id,r=t.data?.id??t.data?._id??t.id;if(n==null||r==null)return;let i=C?.dependenciesField;if(!i)return;let a=m.find(e=>String(e.id??e._id)===String(r))?.[i],o=Fe(a),s=e=>String(typeof e==`object`?e.id:e),c=o.filter(e=>s(e)!==String(n));c.length!==o.length&&await _e(r,a,c)},[C,m,_e]),[be,xe]=(0,t.useState)(null),[Ce,we]=(0,t.useState)(!1),j=(0,t.useCallback)(e=>{xe(e)},[]),Te=(0,t.useCallback)(async()=>{if(!be)return;let t=S?.provider===`object`?S.object:e.objectName;if(!t||!i?.delete){xe(null);return}let n=be.data?.id??be.data?._id??be.id;if(n==null){xe(null);return}we(!0);let r=m;h(e=>e.filter(e=>String(e.id??e._id)!==String(n)));try{await i.delete(t,String(n)),xe(null)}catch(e){console.error(`[ObjectGantt] Failed to delete:`,e),h(r),xe(null)}finally{we(!1)}},[be,S,i,e.objectName,m]);return g?(0,u.jsx)(`div`,{className:l,children:(0,u.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,u.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading Gantt chart...`})})}):v?(0,u.jsx)(`div`,{className:l,children:(0,u.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,u.jsxs)(`div`,{className:`text-destructive`,children:[`Error: `,v.message]})})}):C?(0,u.jsxs)(`div`,{className:l,children:[ce.length>0&&(0,u.jsx)(Me,{filters:ce,value:le,onChange:de,onClear:O,resultCount:fe.length,totalCount:T.length,labels:{all:`全部`,clear:`清除筛选`,empty:`无可选项`,resultSummary:(e,t)=>`显示 ${e} / ${t} 项任务`}}),(0,u.jsx)(`div`,{className:`h-[calc(100vh-200px)] min-h-[600px]`,children:C?.resourceView&&re?(0,u.jsx)(P,{tasks:fe,assignee:re,effort:E,capacity:C?.capacity??1,viewMode:e.viewMode||`day`}):(0,u.jsx)(Se,{tasks:fe,startDate:pe?.start,endDate:pe?.end,onTaskClick:e=>{A.handleClick(e.data),d?.(e.data)},onTaskUpdate:he,onTaskDelete:j,onDependencyCreate:C?.dependenciesField?ve:void 0,onDependencyDelete:C?.dependenciesField?ye:void 0,markers:e.markers,autoSchedule:!!C?.dependenciesField,rescheduleOnConflict:!!C?.dependenciesField,criticalPathDefault:!!e.criticalPath,workingCalendar:ie,showBaselines:e.showBaselines!==!1,readOnly:!!e.readOnly,mobileReadOnly:e.mobileReadOnly!==!1,persistLayoutKey:e.persistLayout===!1?void 0:`${e.objectName||(S?.provider===`object`?S.object:``)||`gantt`}:${e.viewName||`default`}`,groupBy:ne,defaultCollapsedDepth:C?.defaultCollapsedDepth,inlineEdit:!0})}),A.isOverlay&&A.isOpen&&A.selectedRecord&&(()=>{let t=S?.provider===`object`?S.object:e.objectName,n=A.selectedRecord,r=n.id??n._id;if(!t||r==null)return null;let a=C?.titleField?String(n[C.titleField]??`Task Details`):`Task Details`;return(0,u.jsx)(o.RecordDetailDrawer,{open:!0,onClose:A.close,title:a,record:n,objectName:t,recordId:r,dataSource:i,objectSchema:b,width:A.width,fullPageHref:(0,o.deriveRecordPageHref)(t,r)??void 0,onFieldSave:async(e,n)=>{i?.update&&(await i.update(t,String(r),{[e]:n}),h(t=>t.map(t=>String(t.id??t._id)===String(r)?{...t,[e]:n}:t)))},onDelete:async()=>{i?.delete&&(await i.delete(t,String(r)),h(e=>e.filter(e=>String(e.id??e._id)!==String(r))))}})})(),(0,u.jsx)(s.AlertDialog,{open:!!be,onOpenChange:e=>{!e&&!Ce&&xe(null)},children:(0,u.jsxs)(s.AlertDialogContent,{children:[(0,u.jsxs)(s.AlertDialogHeader,{children:[(0,u.jsx)(s.AlertDialogTitle,{children:`Delete this task?`}),(0,u.jsx)(s.AlertDialogDescription,{children:be?(0,u.jsxs)(u.Fragment,{children:[`"`,be.title,`" will be permanently removed. This action cannot be undone.`]}):null})]}),(0,u.jsxs)(s.AlertDialogFooter,{children:[(0,u.jsx)(s.AlertDialogCancel,{disabled:Ce,children:`Cancel`}),(0,u.jsx)(s.AlertDialogAction,{onClick:e=>{e.preventDefault(),Te()},disabled:Ce,"data-testid":`gantt-delete-confirm`,className:`bg-destructive text-destructive-foreground hover:bg-destructive/90`,children:Ce?`Deleting…`:`Delete`})]})]})})]}):(0,u.jsx)(`div`,{className:l,children:(0,u.jsx)(`div`,{className:`flex items-center justify-center h-96`,children:(0,u.jsx)(`div`,{className:`text-muted-foreground`,children:`Gantt configuration required. Please specify startDateField, endDateField, and titleField.`})})})},ze=({schema:e})=>{let{dataSource:t}=(0,r.useSchemaContext)()||{};return(0,u.jsx)(I,{schema:e,dataSource:t})};n.ComponentRegistry.register(`object-gantt`,ze,{namespace:`plugin-gantt`,label:`Object Gantt`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),n.ComponentRegistry.register(`gantt`,ze,{namespace:`view`,label:`Gantt View`,category:`view`,inputs:[{name:`objectName`,type:`string`,label:`Object Name`,required:!0},{name:`gantt`,type:`object`,label:`Gantt Config`,description:`startDateField, endDateField, titleField, progressField, percentageField, colorField, dependenciesField`}]}),e.GanttView=Se,e.ObjectGantt=I,e.ObjectGanttRenderer=ze,e.QuickFilterBar=Me,e.ResourceWorkload=P,e.computeWorkload=we,e.normalizeDependencies=Fe,e.normalizeTaskType=Ne});
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Scheduling helpers for the Gantt — pure, side-effect-free functions over the
3
+ * task graph. Shared by two Phase 6 features:
4
+ *
5
+ * - `computeCriticalPath` — classic CPM (forward ES/EF + backward LS/LF
6
+ * passes) to find the zero-slack chain that drives the project end.
7
+ * - `computeProjectReschedule` — dependency-driven forward shifting: push
8
+ * successors later until every link constraint holds, preserving each
9
+ * task's duration. Tasks are only ever moved *later* (顺延), never pulled
10
+ * earlier, so the result is a minimal repair, not an ASAP recompute.
11
+ *
12
+ * Both treat the dependency on a task as a *predecessor* edge: if task B lists
13
+ * A in `dependencies`, the edge is A → B (A precedes B). Link types:
14
+ * fs finish→start B.start >= A.end (default)
15
+ * ss start →start B.start >= A.start
16
+ * ff finish→finish B.end >= A.end
17
+ * sf start →finish B.end >= A.start
18
+ *
19
+ * Summary (parent) tasks are derived rollups of their children, so they are
20
+ * never *moved* by the reschedule; they still act as fixed predecessor nodes
21
+ * using their current rolled-up dates.
22
+ */
23
+ export type SchedLinkType = 'fs' | 'ss' | 'ff' | 'sf';
24
+ /**
25
+ * Working-calendar model. When supplied to the scheduling functions, durations
26
+ * are measured in *working* days and rescheduled tasks never start on a
27
+ * non-working day. Days are evaluated at UTC midnight granularity.
28
+ */
29
+ export interface WorkingCalendar {
30
+ /** Treat Saturday/Sunday as non-working. */
31
+ skipWeekends?: boolean;
32
+ /** ISO `yyyy-mm-dd` (UTC) keys to treat as non-working (holidays). */
33
+ holidays?: Set<string>;
34
+ }
35
+ export interface SchedulableTask {
36
+ id: string | number;
37
+ start: Date;
38
+ end: Date;
39
+ dependencies?: Array<string | number | {
40
+ id: string | number;
41
+ type?: string;
42
+ }>;
43
+ parent?: string | number | null;
44
+ type?: string;
45
+ }
46
+ export interface CriticalPathResult {
47
+ /** Ids of tasks on the critical path (zero slack). */
48
+ criticalIds: Set<string>;
49
+ /** Critical edges, keyed `predId->succId`. */
50
+ criticalEdges: Set<string>;
51
+ }
52
+ /**
53
+ * Critical-path analysis via CPM. Durations come from each task's
54
+ * start/end span (in days, min 0). The forward/backward passes use
55
+ * finish-to-start semantics for every edge — the standard simplification for
56
+ * critical-path display; the four link types still all contribute edges to the
57
+ * longest-path graph. Returns the zero-slack task ids and the edges joining
58
+ * consecutive critical tasks.
59
+ *
60
+ * When a {@link WorkingCalendar} is supplied, durations are counted in working
61
+ * days (weekends/holidays excluded) so the longest path reflects real effort.
62
+ */
63
+ export declare function computeCriticalPath(tasks: SchedulableTask[], cal?: WorkingCalendar): CriticalPathResult;
64
+ export interface RescheduleChange {
65
+ id: string;
66
+ start: Date;
67
+ end: Date;
68
+ }
69
+ /**
70
+ * Dependency-driven forward reschedule. Walks the graph in topological order
71
+ * and pushes each task as late as its predecessors require, preserving its
72
+ * duration and never moving it earlier than its current start. Summary tasks
73
+ * (parents) are treated as fixed rollup nodes — they constrain successors but
74
+ * are not themselves moved. Returns only the tasks whose dates change.
75
+ *
76
+ * When a {@link WorkingCalendar} is supplied, each task's duration is measured
77
+ * in working days and rescheduled tasks are snapped to start (and finish) on
78
+ * working days only — weekends/holidays are stepped over rather than consumed.
79
+ *
80
+ * Returns an empty array when the graph has a cycle (ambiguous ordering).
81
+ */
82
+ export declare function computeProjectReschedule(tasks: SchedulableTask[], cal?: WorkingCalendar): RescheduleChange[];
83
+ //# sourceMappingURL=scheduling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../src/scheduling.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AAuED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;IACV,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/E,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAkFD,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,8CAA8C;IAC9C,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,EAAE,eAAe,GAAG,kBAAkB,CAiFvG;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;CACX;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,EAAE,eAAe,GAAG,gBAAgB,EAAE,CAkF5G"}
@@ -8,15 +8,12 @@
8
8
  /**
9
9
  * Default English translations for ObjectGantt. Mirrors the
10
10
  * createSafeTranslationHook pattern used by plugin-detail / plugin-timeline so
11
- * the Gantt keeps working when rendered standalone (Storybook, tests, embed)
11
+ * the Gantt keeps working when rendered standalone (unit tests, embed)
12
12
  * without an I18nProvider on the React tree.
13
13
  */
14
14
  export declare const GANTT_DEFAULT_TRANSLATIONS: Record<string, string>;
15
- declare function fallback(key: string, options?: Record<string, unknown>): string;
16
15
  export declare function useGanttTranslation(): {
17
- t: typeof fallback;
18
- } | {
19
- t: import('i18next').TFunction<string, undefined>;
16
+ t: (key: string, options?: Record<string, unknown>) => string;
17
+ language: string | undefined;
20
18
  };
21
- export {};
22
19
  //# sourceMappingURL=useGanttTranslation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGanttTranslation.d.ts","sourceRoot":"","sources":["../src/useGanttTranslation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAyD7D,CAAC;AAYF,wBAAgB,mBAAmB;aAgBf,MAAM,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM;;EAYrE"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Resource / workload model (资源/工作负载视图).
10
+ *
11
+ * Pure, framework-free aggregation that turns a flat task list into a
12
+ * per-resource, per-time-column load histogram. The renderer (ResourceWorkload)
13
+ * draws bars from this; keeping the math here makes it unit-testable and reused
14
+ * identically by the demo and ObjectGantt.
15
+ *
16
+ * Load model — for each resource R and column C:
17
+ * load(R,C) = Σ effort(task) over tasks assigned to R that overlap C
18
+ * A column is "overloaded" when its load exceeds the resource capacity. `effort`
19
+ * defaults to 1 (one full unit of capacity per concurrently-active task) and
20
+ * `capacity` defaults to 1, so out of the box the histogram simply counts
21
+ * concurrent tasks and flags any double-booking (load > 1) as overload.
22
+ */
23
+ export interface WorkloadColumn {
24
+ /** Inclusive start of the column's time span. */
25
+ start: Date;
26
+ /** Exclusive end of the column's time span. */
27
+ end: Date;
28
+ }
29
+ export interface WorkloadOptions<T> {
30
+ /**
31
+ * Resource accessor — the person/team/machine a task loads. Return null to
32
+ * route the task into the "unassigned" bucket.
33
+ */
34
+ assignee: (task: T) => {
35
+ key: string | number;
36
+ label: string;
37
+ } | null;
38
+ /**
39
+ * Capacity units a task consumes per column while active. Default 1 (a task
40
+ * fully occupies its resource). Use e.g. 0.5 for a half-time allocation.
41
+ */
42
+ effort?: (task: T) => number;
43
+ /**
44
+ * Per-resource capacity ceiling. A number applies to every resource; a
45
+ * function can vary it per key. Default 1. Loads above this flag overload.
46
+ */
47
+ capacity?: number | ((key: string) => number);
48
+ /** Label for the bucket of tasks whose `assignee` returns null. */
49
+ unassignedLabel?: string;
50
+ }
51
+ export interface ResourceCell {
52
+ /** Summed effort of overlapping tasks in this column. */
53
+ load: number;
54
+ /** Capacity ceiling for this resource. */
55
+ capacity: number;
56
+ /** load > capacity. */
57
+ overloaded: boolean;
58
+ }
59
+ export interface ResourceLoad {
60
+ key: string;
61
+ label: string;
62
+ capacity: number;
63
+ cells: ResourceCell[];
64
+ /** Highest single-column load — drives the histogram's vertical scale. */
65
+ peak: number;
66
+ /** How many columns are overloaded — a quick "is this resource hot" badge. */
67
+ overloadedCount: number;
68
+ }
69
+ export declare function computeWorkload<T extends {
70
+ start: Date;
71
+ end: Date;
72
+ }>(tasks: T[], columns: WorkloadColumn[], opts: WorkloadOptions<T>): ResourceLoad[];
73
+ //# sourceMappingURL=workload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload.d.ts","sourceRoot":"","sources":["../src/workload.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,KAAK,EAAE,IAAI,CAAC;IACZ,+CAA+C;IAC/C,GAAG,EAAE,IAAI,CAAC;CACX;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK;QAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtE;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAC9C,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAC;CACzB;AAYD,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,EAClE,KAAK,EAAE,CAAC,EAAE,EACV,OAAO,EAAE,cAAc,EAAE,EACzB,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,GACvB,YAAY,EAAE,CAuChB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-gantt",
3
- "version": "6.2.3",
3
+ "version": "7.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Gantt chart plugin for Object UI",
@@ -24,26 +24,27 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "@objectstack/spec": "^6.7.1",
28
- "lucide-react": "^1.16.0",
29
- "@object-ui/components": "6.2.3",
30
- "@object-ui/core": "6.2.3",
31
- "@object-ui/fields": "6.2.3",
32
- "@object-ui/plugin-detail": "6.2.3",
33
- "@object-ui/react": "6.2.3",
34
- "@object-ui/types": "6.2.3"
27
+ "@objectstack/spec": "^10.0.0",
28
+ "lucide-react": "^1.21.0",
29
+ "@object-ui/components": "7.0.0",
30
+ "@object-ui/core": "7.0.0",
31
+ "@object-ui/fields": "7.0.0",
32
+ "@object-ui/i18n": "7.0.0",
33
+ "@object-ui/plugin-detail": "7.0.0",
34
+ "@object-ui/react": "7.0.0",
35
+ "@object-ui/types": "7.0.0"
35
36
  },
36
37
  "peerDependencies": {
37
38
  "react": "^18.0.0 || ^19.0.0",
38
39
  "react-dom": "^18.0.0 || ^19.0.0"
39
40
  },
40
41
  "devDependencies": {
41
- "@types/react": "19.2.15",
42
+ "@types/react": "19.2.17",
42
43
  "@types/react-dom": "19.2.3",
43
44
  "@vitejs/plugin-react": "^6.0.2",
44
45
  "typescript": "^6.0.3",
45
- "vite": "^8.0.14",
46
- "vite-plugin-dts": "^5.0.1"
46
+ "vite": "^8.0.16",
47
+ "vite-plugin-dts": "^5.0.2"
47
48
  },
48
49
  "keywords": [
49
50
  "objectui",