@fullcalendar/timeline
Advanced tools
Comparing version 6.1.15 to 7.0.0-beta.0
/*! | ||
FullCalendar Timeline Plugin v6.1.15 | ||
FullCalendar Timeline Plugin v7.0.0-beta.0 | ||
Docs & License: https://fullcalendar.io/docs/timeline-view-no-resources | ||
(c) 2024 Adam Shaw | ||
*/ | ||
FullCalendar.Timeline=function(e,t,n,i,o,r){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}var s=l(n);i.config.MAX_TIMELINE_SLOTS=1e3;const a=[{years:1},{months:1},{days:1},{hours:1},{minutes:30},{minutes:15},{minutes:10},{minutes:5},{minutes:1},{seconds:30},{seconds:15},{seconds:10},{seconds:5},{seconds:1},{milliseconds:500},{milliseconds:100},{milliseconds:10},{milliseconds:1}];function c(e,t,n,o){let r={labelInterval:n.slotLabelInterval,slotDuration:n.slotDuration};!function(e,t,n){const{currentRange:o}=t;if(e.labelInterval){n.countDurationsBetween(o.start,o.end,e.labelInterval)>i.config.MAX_TIMELINE_SLOTS&&(console.warn("slotLabelInterval results in too many cells"),e.labelInterval=null)}if(e.slotDuration){n.countDurationsBetween(o.start,o.end,e.slotDuration)>i.config.MAX_TIMELINE_SLOTS&&(console.warn("slotDuration results in too many cells"),e.slotDuration=null)}if(e.labelInterval&&e.slotDuration){const t=i.wholeDivideDurations(e.labelInterval,e.slotDuration);(null===t||t<1)&&(console.warn("slotLabelInterval must be a multiple of slotDuration"),e.slotDuration=null)}}(r,e,t),u(r,e,t),function(e,t,n){const{currentRange:o}=t;let{slotDuration:r}=e;if(!r){const l=u(e,t,n);for(let e of a){const t=i.createDuration(e),n=i.wholeDivideDurations(l,t);if(null!==n&&n>1&&n<=6){r=t;break}}if(r){n.countDurationsBetween(o.start,o.end,r)>200&&(r=null)}r||(r=l),e.slotDuration=r}}(r,e,t);let l=n.slotLabelFormat,s=Array.isArray(l)?l:null!=l?[l]:function(e,t,n,o){let r,l;const{labelInterval:s}=e;let a=i.greatestDurationDenominator(s).unit;const c=o.weekNumbers;let d=r=l=null;"week"!==a||c||(a="day");switch(a){case"year":d={year:"numeric"};break;case"month":h("years",t,n)>1&&(d={year:"numeric"}),r={month:"short"};break;case"week":h("years",t,n)>1&&(d={year:"numeric"}),r={week:"narrow"};break;case"day":h("years",t,n)>1?d={year:"numeric",month:"long"}:h("months",t,n)>1&&(d={month:"long"}),c&&(r={week:"short"}),l={weekday:"narrow",day:"numeric"};break;case"hour":c&&(d={week:"short"}),h("days",t,n)>1&&(r={weekday:"short",day:"numeric",month:"numeric",omitCommas:!0}),l={hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"};break;case"minute":i.asRoughMinutes(s)/60>=6?(d={hour:"numeric",meridiem:"short"},r=e=>":"+i.padStart(e.date.minute,2)):d={hour:"numeric",minute:"numeric",meridiem:"short"};break;case"second":i.asRoughSeconds(s)/60>=6?(d={hour:"numeric",minute:"2-digit",meridiem:"lowercase"},r=e=>":"+i.padStart(e.date.second,2)):d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"};break;case"millisecond":d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"},r=e=>"."+i.padStart(e.millisecond,3)}return[].concat(d||[],r||[],l||[])}(r,e,t,n);r.headerFormats=s.map(e=>i.createFormatter(e)),r.isTimeScale=Boolean(r.slotDuration.milliseconds);let c=null;if(!r.isTimeScale){const e=i.greatestDurationDenominator(r.slotDuration).unit;/year|month|week/.test(e)&&(c=e)}r.largeUnit=c,r.emphasizeWeeks=1===i.asCleanDays(r.slotDuration)&&h("weeks",e,t)>=2&&!n.businessHours;let g,p,v=n.snapDuration;v&&(g=i.createDuration(v),p=i.wholeDivideDurations(r.slotDuration,g)),null==p&&(g=r.slotDuration,p=1),r.snapDuration=g,r.snapsPerSlot=p;let D=i.asRoughMs(e.slotMaxTime)-i.asRoughMs(e.slotMinTime),S=d(e.renderRange.start,r,t),b=d(e.renderRange.end,r,t);r.isTimeScale&&(S=t.add(S,e.slotMinTime),b=t.add(i.addDays(b,-1),e.slotMaxTime)),r.timeWindowMs=D,r.normalizedRange={start:S,end:b};let C=[],R=S;for(;R<b;)m(R,r,e,o)&&C.push(R),R=t.add(R,r.slotDuration);r.slotDates=C;let y=-1,w=0;const E=[],x=[];for(R=S;R<b;)m(R,r,e,o)?(y+=1,E.push(y),x.push(w)):E.push(y+.5),R=t.add(R,r.snapDuration),w+=1;return r.snapDiffToIndex=E,r.snapIndexToDiff=x,r.snapCnt=y+1,r.slotCnt=r.snapCnt/r.snapsPerSlot,r.isWeekStarts=function(e,t){let{slotDates:n,emphasizeWeeks:i}=e,o=null,r=[];for(let e of n){let n=t.computeWeekNumber(e),l=i&&null!==o&&o!==n;o=n,r.push(l)}return r}(r,t),r.cellRows=function(e,t){let n=e.slotDates,o=e.headerFormats,r=o.map(()=>[]),l=i.asCleanDays(e.slotDuration),s=7===l?"week":1===l?"day":null,a=o.map(e=>e.getLargestUnit?e.getLargestUnit():null);for(let l=0;l<n.length;l+=1){let c=n[l],d=e.isWeekStarts[l];for(let n=0;n<o.length;n+=1){let l=o[n],m=r[n],u=m[m.length-1],h=n===o.length-1,g=o.length>1&&!h,p=null,v=a[n]||(h?s:null);if(g){let e=t.format(c,l);u&&u.text===e?u.colspan+=1:p=f(c,e,v)}else if(!u||i.isInt(t.countDurationsBetween(e.normalizedRange.start,c,e.labelInterval))){let e=t.format(c,l);p=f(c,e,v)}else u.colspan+=1;p&&(p.weekStart=d,m.push(p))}}return r}(r,t),r.slotsPerLabel=i.wholeDivideDurations(r.labelInterval,r.slotDuration),r}function d(e,t,n){let o=e;return t.isTimeScale||(o=i.startOfDay(o),t.largeUnit&&(o=n.startOf(o,t.largeUnit))),o}function m(e,t,n,o){if(o.isHiddenDay(e))return!1;if(t.isTimeScale){let o=i.startOfDay(e),r=e.valueOf()-o.valueOf()-i.asRoughMs(n.slotMinTime);return r=(r%864e5+864e5)%864e5,r<t.timeWindowMs}return!0}function u(e,t,n){const{currentRange:o}=t;let{labelInterval:r}=e;if(!r){let t;if(e.slotDuration){for(t of a){const n=i.createDuration(t),o=i.wholeDivideDurations(n,e.slotDuration);if(null!==o&&o<=6){r=n;break}}r||(r=e.slotDuration)}else for(t of a){r=i.createDuration(t);if(n.countDurationsBetween(o.start,o.end,r)>=18)break}e.labelInterval=r}return r}function h(e,t,n){let o=t.currentRange,r=null;return"years"===e?r=n.diffWholeYears(o.start,o.end):"months"===e||"weeks"===e?r=n.diffWholeMonths(o.start,o.end):"days"===e&&(r=i.diffWholeDays(o.start,o.end)),r||0}function f(e,t,n){return{date:e,text:t,rowUnit:n,colspan:1,isWeekStart:!1}}class g extends i.BaseComponent{constructor(){super(...arguments),this.refineRenderProps=i.memoizeObjArg(D),this.buildCellNavLinkAttrs=i.memoize(p)}render(){let{props:e,context:t}=this,{dateEnv:n,options:r}=t,{cell:l,dateProfile:s,tDateProfile:a}=e,c=i.getDateMeta(l.date,e.todayRange,e.nowDate,s),d=this.refineRenderProps({level:e.rowLevel,dateMarker:l.date,text:l.text,dateEnv:t.dateEnv,viewApi:t.viewApi});return o.createElement(i.ContentContainer,{elTag:"th",elClasses:["fc-timeline-slot","fc-timeline-slot-label",l.isWeekStart&&"fc-timeline-slot-em",..."time"===l.rowUnit?i.getSlotClassNames(c,t.theme):i.getDayClassNames(c,t.theme)],elAttrs:{colSpan:l.colspan,"data-date":n.formatIso(l.date,{omitTime:!a.isTimeScale,omitTimeZoneOffset:!0})},renderProps:d,generatorName:"slotLabelContent",customGenerator:r.slotLabelContent,defaultGenerator:v,classNameGenerator:r.slotLabelClassNames,didMount:r.slotLabelDidMount,willUnmount:r.slotLabelWillUnmount},n=>o.createElement("div",{className:"fc-timeline-slot-frame",style:{height:e.rowInnerHeight}},o.createElement(n,{elTag:"a",elClasses:["fc-timeline-slot-cushion","fc-scrollgrid-sync-inner",e.isSticky&&"fc-sticky"],elAttrs:this.buildCellNavLinkAttrs(t,l.date,l.rowUnit)})))}}function p(e,t,n){return n&&"time"!==n?i.buildNavLinkAttrs(e,t,n):{}}function v(e){return e.text}function D(e){return{level:e.level,date:e.dateEnv.toDate(e.dateMarker),view:e.viewApi,text:e.text}}class S extends i.BaseComponent{render(){let{dateProfile:e,tDateProfile:t,rowInnerHeights:n,todayRange:i,nowDate:r}=this.props,{cellRows:l}=t;return o.createElement(o.Fragment,null,l.map((s,a)=>{let c=a===l.length-1,d=["fc-timeline-header-row",t.isTimeScale&&c?"fc-timeline-header-row-chrono":""];return o.createElement("tr",{key:a,className:d.join(" ")},s.map(l=>o.createElement(g,{key:l.date.toISOString(),cell:l,rowLevel:a,dateProfile:e,tDateProfile:t,todayRange:i,nowDate:r,rowInnerHeight:n&&n[a],isSticky:!c})))}))}}class b{constructor(e,t,n,o,r,l){this.slatRootEl=e,this.dateProfile=n,this.tDateProfile=o,this.dateEnv=r,this.isRtl=l,this.outerCoordCache=new i.PositionCache(e,t,!0,!1),this.innerCoordCache=new i.PositionCache(e,i.findDirectChildren(t,"div"),!0,!1)}isDateInRange(e){return i.rangeContainsMarker(this.dateProfile.currentRange,e)}dateToCoord(e){let{tDateProfile:t}=this,n=this.computeDateSnapCoverage(e)/t.snapsPerSlot,i=Math.floor(n);i=Math.min(i,t.slotCnt-1);let o=n-i,{innerCoordCache:r,outerCoordCache:l}=this;return this.isRtl?l.originClientRect.width-(l.rights[i]-r.getWidth(i)*o):l.lefts[i]+r.getWidth(i)*o}rangeToCoords(e){return{start:this.dateToCoord(e.start),end:this.dateToCoord(e.end)}}durationToCoord(e){let{dateProfile:t,tDateProfile:n,dateEnv:o,isRtl:r}=this,l=0;if(t){let s=o.add(t.activeRange.start,e);n.isTimeScale||(s=i.startOfDay(s)),l=this.dateToCoord(s),!r&&l&&(l+=1)}return l}coordFromLeft(e){return this.isRtl?this.outerCoordCache.originClientRect.width-e:e}computeDateSnapCoverage(e){return C(e,this.tDateProfile,this.dateEnv)}}function C(e,t,n){let o=n.countDurationsBetween(t.normalizedRange.start,e,t.snapDuration);if(o<0)return 0;if(o>=t.snapDiffToIndex.length)return t.snapCnt;let r=Math.floor(o),l=t.snapDiffToIndex[r];return i.isInt(l)?l+=o-r:l=Math.ceil(l),l}function R(e,t){return null===e?{left:"",right:""}:t?{right:e,left:""}:{left:e,right:""}}function y(e,t){return e?t?{right:e.start,left:-e.end}:{left:e.start,right:-e.end}:{left:"",right:""}}class w extends i.BaseComponent{constructor(){super(...arguments),this.rootElRef=o.createRef()}render(){let{props:e,context:t}=this,n=i.greatestDurationDenominator(e.tDateProfile.slotDuration).unit,r=e.slatCoords&&e.slatCoords.dateProfile===e.dateProfile?e.slatCoords:null;return o.createElement(i.NowTimer,{unit:n},(n,l)=>o.createElement("div",{className:"fc-timeline-header",ref:this.rootElRef},o.createElement("table",{"aria-hidden":!0,className:"fc-scrollgrid-sync-table",style:{minWidth:e.tableMinWidth,width:e.clientWidth}},e.tableColGroupNode,o.createElement("tbody",null,o.createElement(S,{dateProfile:e.dateProfile,tDateProfile:e.tDateProfile,nowDate:n,todayRange:l,rowInnerHeights:e.rowInnerHeights}))),t.options.nowIndicator&&o.createElement("div",{className:"fc-timeline-now-indicator-container"},r&&r.isDateInRange(n)&&o.createElement(i.NowIndicatorContainer,{elClasses:["fc-timeline-now-indicator-arrow"],elStyle:R(r.dateToCoord(n),t.isRtl),isAxis:!0,date:n}))))}componentDidMount(){this.updateSize()}componentDidUpdate(){this.updateSize()}updateSize(){this.props.onMaxCushionWidth&&this.props.onMaxCushionWidth(this.computeMaxCushionWidth())}computeMaxCushionWidth(){return Math.max(...i.findElements(this.rootElRef.current,".fc-timeline-header-row:last-child .fc-timeline-slot-cushion").map(e=>e.getBoundingClientRect().width))}}class E extends i.BaseComponent{render(){let{props:e,context:t}=this,{dateEnv:n,options:r,theme:l}=t,{date:s,tDateProfile:a,isEm:c}=e,d=i.getDateMeta(e.date,e.todayRange,e.nowDate,e.dateProfile),m=Object.assign(Object.assign({date:n.toDate(e.date)},d),{view:t.viewApi});return o.createElement(i.ContentContainer,{elTag:"td",elRef:e.elRef,elClasses:["fc-timeline-slot","fc-timeline-slot-lane",c&&"fc-timeline-slot-em",a.isTimeScale?i.isInt(n.countDurationsBetween(a.normalizedRange.start,e.date,a.labelInterval))?"fc-timeline-slot-major":"fc-timeline-slot-minor":"",...e.isDay?i.getDayClassNames(d,l):i.getSlotClassNames(d,l)],elAttrs:{"data-date":n.formatIso(s,{omitTimeZoneOffset:!0,omitTime:!a.isTimeScale})},renderProps:m,generatorName:"slotLaneContent",customGenerator:r.slotLaneContent,classNameGenerator:r.slotLaneClassNames,didMount:r.slotLaneDidMount,willUnmount:r.slotLaneWillUnmount},e=>o.createElement(e,{elTag:"div"}))}}class x extends i.BaseComponent{render(){let{props:e}=this,{tDateProfile:t,cellElRefs:n}=e,{slotDates:i,isWeekStarts:r}=t,l=!t.isTimeScale&&!t.largeUnit;return o.createElement("tbody",null,o.createElement("tr",null,i.map((i,s)=>{let a=i.toISOString();return o.createElement(E,{key:a,elRef:n.createRef(a),date:i,dateProfile:e.dateProfile,tDateProfile:t,nowDate:e.nowDate,todayRange:e.todayRange,isEm:r[s],isDay:l})})))}}class k extends i.BaseComponent{constructor(){super(...arguments),this.rootElRef=o.createRef(),this.cellElRefs=new i.RefMap,this.handleScrollRequest=e=>{let{onScrollLeftRequest:t}=this.props,{coords:n}=this;if(t&&n){if(e.time){t(n.coordFromLeft(n.durationToCoord(e.time)))}return!0}return null}}render(){let{props:e,context:t}=this;return o.createElement("div",{className:"fc-timeline-slots",ref:this.rootElRef},o.createElement("table",{"aria-hidden":!0,className:t.theme.getClass("table"),style:{minWidth:e.tableMinWidth,width:e.clientWidth}},e.tableColGroupNode,o.createElement(x,{cellElRefs:this.cellElRefs,dateProfile:e.dateProfile,tDateProfile:e.tDateProfile,nowDate:e.nowDate,todayRange:e.todayRange})))}componentDidMount(){this.updateSizing(),this.scrollResponder=this.context.createScrollResponder(this.handleScrollRequest)}componentDidUpdate(e){this.updateSizing(),this.scrollResponder.update(e.dateProfile!==this.props.dateProfile)}componentWillUnmount(){this.scrollResponder.detach(),this.props.onCoords&&this.props.onCoords(null)}updateSizing(){let{props:e,context:t}=this;if(null!==e.clientWidth&&this.scrollResponder){this.rootElRef.current.offsetWidth&&(this.coords=new b(this.rootElRef.current,(n=this.cellElRefs.currentMap,e.tDateProfile.slotDates.map(e=>{let t=e.toISOString();return n[t]})),e.dateProfile,e.tDateProfile,t.dateEnv,t.isRtl),e.onCoords&&e.onCoords(this.coords),this.scrollResponder.update(!1))}var n}positionToHit(e){let{outerCoordCache:t}=this.coords,{dateEnv:n,isRtl:o}=this.context,{tDateProfile:r}=this.props,l=t.leftToIndex(e);if(null!=l){let s=t.getWidth(l),a=o?(t.rights[l]-e)/s:(e-t.lefts[l])/s,c=Math.floor(a*r.snapsPerSlot),d=n.add(r.slotDates[l],i.multiplyDuration(r.snapDuration,c));return{dateSpan:{range:{start:d,end:n.add(d,r.snapDuration)},allDay:!this.props.tDateProfile.isTimeScale},dayEl:this.cellElRefs.currentMap[l],left:t.lefts[l],right:t.rights[l]}}return null}}function P(e,t,n){let i=[];if(n)for(let o of e){let e=n.rangeToCoords(o),r=Math.round(e.start),l=Math.round(e.end);l-r<t&&(l=r+t),i.push({start:r,end:l})}return i}class M extends i.BaseComponent{render(){let{props:e}=this,t=[].concat(e.eventResizeSegs,e.dateSelectionSegs);return e.timelineCoords&&o.createElement("div",{className:"fc-timeline-bg"},this.renderSegs(e.businessHourSegs||[],e.timelineCoords,"non-business"),this.renderSegs(e.bgEventSegs||[],e.timelineCoords,"bg-event"),this.renderSegs(t,e.timelineCoords,"highlight"))}renderSegs(e,t,n){let{todayRange:r,nowDate:l}=this.props,{isRtl:s}=this.context,a=P(e,0,t),c=e.map((e,t)=>{let c=y(a[t],s);return o.createElement("div",{key:i.buildEventRangeKey(e.eventRange),className:"fc-timeline-bg-harness",style:c},"bg-event"===n?o.createElement(i.BgEvent,Object.assign({seg:e},i.getSegMeta(e,r,l))):i.renderFill(n))});return o.createElement(o.Fragment,null,c)}}class T extends i.Slicer{sliceRange(e,t,n,o,r){let l=function(e,t,n){if(!t.isTimeScale&&(e=i.computeVisibleDayRange(e),t.largeUnit)){let i=e;((e={start:n.startOf(e.start,t.largeUnit),end:n.startOf(e.end,t.largeUnit)}).end.valueOf()!==i.end.valueOf()||e.end<=e.start)&&(e={start:e.start,end:n.add(e.end,t.slotDuration)})}return e}(e,o,r),s=[];if(C(l.start,o,r)<C(l.end,o,r)){let e=i.intersectRanges(l,o.normalizedRange);e&&s.push({start:e.start,end:e.end,isStart:e.start.valueOf()===l.start.valueOf()&&m(e.start,o,t,n),isEnd:e.end.valueOf()===l.end.valueOf()&&m(i.addMs(e.end,-1),o,t,n)})}return s}}const I=i.createFormatter({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"});class W extends i.BaseComponent{render(){let{props:e}=this;return o.createElement(i.StandardEvent,Object.assign({},e,{elClasses:["fc-timeline-event","fc-h-event"],defaultTimeFormat:I,defaultDisplayEventTime:!e.isTimeScale}))}}class z extends i.BaseComponent{render(){let{props:e,context:t}=this,{hiddenSegs:n,placement:r,resourceId:l}=e,{top:s,hcoords:a}=r,c=a&&null!==s,d=y(a,t.isRtl),m=l?{resourceId:l}:{};return o.createElement(i.MoreLinkContainer,{elRef:e.elRef,elClasses:["fc-timeline-more-link"],elStyle:Object.assign({visibility:c?"":"hidden",top:s||0},d),allDayDate:null,moreCnt:n.length,allSegs:n,hiddenSegs:n,dateProfile:e.dateProfile,todayRange:e.todayRange,extraDateSpan:m,popoverContent:()=>o.createElement(o.Fragment,null,n.map(t=>{let n=t.eventRange.instance.instanceId;return o.createElement("div",{key:n,style:{visibility:e.isForcedInvisible[n]?"hidden":""}},o.createElement(W,Object.assign({isTimeScale:e.isTimeScale,seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:n===e.eventSelection},i.getSegMeta(t,e.todayRange,e.nowDate))))}))},e=>o.createElement(e,{elTag:"div",elClasses:["fc-timeline-more-link-inner","fc-sticky"]}))}}class L extends i.BaseComponent{constructor(){super(...arguments),this.slicer=new T,this.sortEventSegs=i.memoize(i.sortEventSegs),this.harnessElRefs=new i.RefMap,this.moreElRefs=new i.RefMap,this.innerElRef=o.createRef(),this.state={eventInstanceHeights:{},moreLinkHeights:{}},this.handleResize=e=>{e&&this.updateSize()}}render(){let{props:e,state:t,context:n}=this,{options:r}=n,{dateProfile:l,tDateProfile:s}=e,a=this.slicer.sliceProps(e,l,s.isTimeScale?null:e.nextDayThreshold,n,l,n.dateProfileGenerator,s,n.dateEnv),c=(a.eventDrag?a.eventDrag.segs:null)||(a.eventResize?a.eventResize.segs:null)||[],d=this.sortEventSegs(a.fgEventSegs,r.eventOrder),m=P(d,r.eventMinWidth,e.timelineCoords),[u,h]=function(e,t,n,o,r,l){let s=[],a=[];for(let i=0;i<e.length;i+=1){let o=e[i],r=n[o.eventRange.instance.instanceId],l=t[i];r&&l?s.push({index:i,span:l,thickness:r}):a.push({seg:o,hcoords:l,top:null})}let c=new i.SegHierarchy;null!=r&&(c.strictOrder=r),null!=l&&(c.maxStackCnt=l);let d=c.addSegs(s),m=d.map(t=>({seg:e[t.index],hcoords:t.span,top:null})),u=i.groupIntersectingEntries(d),h=[],f=[];const g=t=>e[t.index];for(let t=0;t<u.length;t+=1){let n=u[t],r=n.entries.map(g),l=o[i.buildIsoString(i.computeEarliestSegStart(r))];null!=l?h.push({index:e.length+t,thickness:l,span:n.span}):f.push({seg:r,hcoords:n.span,top:null})}c.maxStackCnt=-1,c.addSegs(h);let p=c.toRects(),v=[],D=0;for(let t of p){let n=t.index;v.push({seg:n<e.length?e[n]:u[n-e.length].entries.map(g),hcoords:t.span,top:t.levelCoord}),D=Math.max(D,t.levelCoord+t.thickness)}return[v.concat(a,m,f),D]}(d,m,t.eventInstanceHeights,t.moreLinkHeights,r.eventOrderStrict,r.eventMaxStack),f=(a.eventDrag?a.eventDrag.affectedInstances:null)||(a.eventResize?a.eventResize.affectedInstances:null)||{};return o.createElement(o.Fragment,null,o.createElement(M,{businessHourSegs:a.businessHourSegs,bgEventSegs:a.bgEventSegs,timelineCoords:e.timelineCoords,eventResizeSegs:a.eventResize?a.eventResize.segs:[],dateSelectionSegs:a.dateSelectionSegs,nowDate:e.nowDate,todayRange:e.todayRange}),o.createElement("div",{className:"fc-timeline-events fc-scrollgrid-sync-inner",ref:this.innerElRef,style:{height:h}},this.renderFgSegs(u,f,!1,!1,!1),this.renderFgSegs(function(e,t,n){if(!e.length||!t)return[];let i=function(e){let t={};for(let n of e){let{seg:e}=n;Array.isArray(e)||(t[e.eventRange.instance.instanceId]=n.top)}return t}(n);return e.map(e=>({seg:e,hcoords:t.rangeToCoords(e),top:i[e.eventRange.instance.instanceId]}))}(c,e.timelineCoords,u),{},Boolean(a.eventDrag),Boolean(a.eventResize),!1)))}componentDidMount(){this.updateSize(),this.context.addResizeHandler(this.handleResize)}componentDidUpdate(e,t){e.eventStore===this.props.eventStore&&e.timelineCoords===this.props.timelineCoords&&t.moreLinkHeights===this.state.moreLinkHeights||this.updateSize()}componentWillUnmount(){this.context.removeResizeHandler(this.handleResize)}updateSize(){let{props:e}=this,{timelineCoords:t}=e;const n=this.innerElRef.current;e.onHeightChange&&e.onHeightChange(n,!1),t&&this.setState({eventInstanceHeights:i.mapHash(this.harnessElRefs.currentMap,e=>Math.round(e.getBoundingClientRect().height)),moreLinkHeights:i.mapHash(this.moreElRefs.currentMap,e=>Math.round(e.getBoundingClientRect().height))},()=>{e.onHeightChange&&e.onHeightChange(n,!0)}),e.syncParentMinHeight&&(n.parentElement.style.minHeight=n.style.height)}renderFgSegs(e,t,n,r,l){let{harnessElRefs:s,moreElRefs:a,props:c,context:d}=this,m=n||r||l;return o.createElement(o.Fragment,null,e.map(e=>{let{seg:u,hcoords:h,top:f}=e;if(Array.isArray(u)){let n=i.buildIsoString(i.computeEarliestSegStart(u));return o.createElement(z,{key:"m:"+n,elRef:a.createRef(n),hiddenSegs:u,placement:e,dateProfile:c.dateProfile,nowDate:c.nowDate,todayRange:c.todayRange,isTimeScale:c.tDateProfile.isTimeScale,eventSelection:c.eventSelection,resourceId:c.resourceId,isForcedInvisible:t})}let g=u.eventRange.instance.instanceId,p=m||Boolean(!t[g]&&h&&null!==f),v=y(h,d.isRtl);return o.createElement("div",{key:"e:"+g,ref:m?null:s.createRef(g),className:"fc-timeline-event-harness",style:Object.assign({visibility:p?"":"hidden",top:f||0},v)},o.createElement(W,Object.assign({isTimeScale:c.tDateProfile.isTimeScale,seg:u,isDragging:n,isResizing:r,isDateSelecting:l,isSelected:g===c.eventSelection},i.getSegMeta(u,c.todayRange,c.nowDate))))}))}}L.addStateEquality({eventInstanceHeights:i.isPropsEqual,moreLinkHeights:i.isPropsEqual});class H extends i.DateComponent{constructor(){super(...arguments),this.slatsRef=o.createRef(),this.state={coords:null},this.handeEl=e=>{e?this.context.registerInteractiveComponent(this,{el:e}):this.context.unregisterInteractiveComponent(this)},this.handleCoords=e=>{this.setState({coords:e}),this.props.onSlatCoords&&this.props.onSlatCoords(e)}}render(){let{props:e,state:t,context:n}=this,{options:r}=n,{dateProfile:l,tDateProfile:s}=e,a=i.greatestDurationDenominator(s.slotDuration).unit;return o.createElement("div",{className:"fc-timeline-body",ref:this.handeEl,style:{minWidth:e.tableMinWidth,height:e.clientHeight,width:e.clientWidth}},o.createElement(i.NowTimer,{unit:a},(a,c)=>o.createElement(o.Fragment,null,o.createElement(k,{ref:this.slatsRef,dateProfile:l,tDateProfile:s,nowDate:a,todayRange:c,clientWidth:e.clientWidth,tableColGroupNode:e.tableColGroupNode,tableMinWidth:e.tableMinWidth,onCoords:this.handleCoords,onScrollLeftRequest:e.onScrollLeftRequest}),o.createElement(L,{dateProfile:l,tDateProfile:e.tDateProfile,nowDate:a,todayRange:c,nextDayThreshold:r.nextDayThreshold,businessHours:e.businessHours,eventStore:e.eventStore,eventUiBases:e.eventUiBases,dateSelection:e.dateSelection,eventSelection:e.eventSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,timelineCoords:t.coords,syncParentMinHeight:!0}),r.nowIndicator&&t.coords&&t.coords.isDateInRange(a)&&o.createElement("div",{className:"fc-timeline-now-indicator-container"},o.createElement(i.NowIndicatorContainer,{elClasses:["fc-timeline-now-indicator-line"],elStyle:R(t.coords.dateToCoord(a),n.isRtl),isAxis:!1,date:a})))))}queryHit(e,t,n,i){let o=this.slatsRef.current.positionToHit(e);return o?{dateProfile:this.props.dateProfile,dateSpan:o.dateSpan,rect:{left:o.left,right:o.right,top:0,bottom:i},dayEl:o.dayEl,layer:0}:null}}class N extends i.DateComponent{constructor(){super(...arguments),this.buildTimelineDateProfile=i.memoize(c),this.scrollGridRef=o.createRef(),this.state={slatCoords:null,slotCushionMaxWidth:null},this.handleSlatCoords=e=>{this.setState({slatCoords:e})},this.handleScrollLeftRequest=e=>{this.scrollGridRef.current.forceScrollLeft(0,e)},this.handleMaxCushionWidth=e=>{this.setState({slotCushionMaxWidth:Math.ceil(e)})}}render(){let{props:e,state:t,context:n}=this,{options:l}=n,s=!e.forPrint&&i.getStickyHeaderDates(l),a=!e.forPrint&&i.getStickyFooterScrollbar(l),c=this.buildTimelineDateProfile(e.dateProfile,n.dateEnv,l,n.dateProfileGenerator),{slotMinWidth:d}=l,m=O(c,d||this.computeFallbackSlotMinWidth(c)),u=[{type:"header",key:"header",isSticky:s,chunks:[{key:"timeline",content:n=>o.createElement(w,{dateProfile:e.dateProfile,clientWidth:n.clientWidth,clientHeight:n.clientHeight,tableMinWidth:n.tableMinWidth,tableColGroupNode:n.tableColGroupNode,tDateProfile:c,slatCoords:t.slatCoords,onMaxCushionWidth:d?null:this.handleMaxCushionWidth})}]},{type:"body",key:"body",liquid:!0,chunks:[{key:"timeline",content:t=>o.createElement(H,Object.assign({},e,{clientWidth:t.clientWidth,clientHeight:t.clientHeight,tableMinWidth:t.tableMinWidth,tableColGroupNode:t.tableColGroupNode,tDateProfile:c,onSlatCoords:this.handleSlatCoords,onScrollLeftRequest:this.handleScrollLeftRequest}))}]}];return a&&u.push({type:"footer",key:"footer",isSticky:!0,chunks:[{key:"timeline",content:i.renderScrollShim}]}),o.createElement(i.ViewContainer,{elClasses:["fc-timeline",!1===l.eventOverlap?"fc-timeline-overlap-disabled":""],viewSpec:n.viewSpec},o.createElement(r.ScrollGrid,{ref:this.scrollGridRef,liquid:!e.isHeightAuto&&!e.forPrint,forPrint:e.forPrint,collapsibleWidth:!1,colGroups:[{cols:m}],sections:u}))}computeFallbackSlotMinWidth(e){return Math.max(30,(this.state.slotCushionMaxWidth||0)/e.slotsPerLabel)}}function O(e,t){return[{span:e.slotCnt,minWidth:t||1}]}i.injectStyles('.fc .fc-timeline-body{min-height:100%;position:relative;z-index:1}.fc .fc-timeline-slots{bottom:0;position:absolute;top:0;z-index:1}.fc .fc-timeline-slots>table{height:100%}.fc .fc-timeline-slot-minor{border-style:dotted}.fc .fc-timeline-slot-frame{align-items:center;display:flex;justify-content:center}.fc .fc-timeline-header-row-chrono .fc-timeline-slot-frame{justify-content:flex-start}.fc .fc-timeline-header-row:last-child .fc-timeline-slot-frame{overflow:hidden}.fc .fc-timeline-slot-cushion{padding:4px 5px;white-space:nowrap}.fc-direction-ltr .fc-timeline-slot{border-right:0!important}.fc-direction-rtl .fc-timeline-slot{border-left:0!important}.fc .fc-timeline-now-indicator-container{bottom:0;left:0;position:absolute;right:0;top:0;width:0;z-index:4}.fc .fc-timeline-now-indicator-arrow,.fc .fc-timeline-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;pointer-events:none;position:absolute;top:0}.fc .fc-timeline-now-indicator-arrow{border-left-color:transparent;border-right-color:transparent;border-width:6px 5px 0;margin:0 -6px}.fc .fc-timeline-now-indicator-line{border-width:0 0 0 1px;bottom:0;margin:0 -1px}.fc .fc-timeline-events{position:relative;width:0;z-index:3}.fc .fc-timeline-event-harness,.fc .fc-timeline-more-link{position:absolute;top:0}.fc-timeline-event{z-index:1}.fc-timeline-event.fc-event-mirror{z-index:2}.fc-timeline-event{align-items:center;border-radius:0;display:flex;font-size:var(--fc-small-font-size);margin-bottom:1px;padding:2px 1px;position:relative}.fc-timeline-event .fc-event-main{flex-grow:1;flex-shrink:1;min-width:0}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px;white-space:nowrap}.fc-direction-ltr .fc-timeline-event.fc-event-end,.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end,.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-overlap-disabled .fc-timeline-event{margin-bottom:0;padding-bottom:5px;padding-top:5px}.fc-timeline-event:not(.fc-event-end):after,.fc-timeline-event:not(.fc-event-start):before{border-color:transparent #000;border-style:solid;border-width:5px;content:"";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start):before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end):after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end):after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start):before{border-right:0}.fc-timeline-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;font-size:var(--fc-small-font-size);padding:1px}.fc-timeline-more-link-inner{display:inline-block;left:0;padding:2px;right:0}.fc .fc-timeline-bg{bottom:0;left:0;position:absolute;right:0;top:0;width:0;z-index:2}.fc .fc-timeline-bg .fc-non-business{z-index:1}.fc .fc-timeline-bg .fc-bg-event{z-index:2}.fc .fc-timeline-bg .fc-highlight{z-index:3}.fc .fc-timeline-bg-harness{bottom:0;position:absolute;top:0}');var F=t.createPlugin({name:"@fullcalendar/timeline",premiumReleaseDate:"2024-07-12",deps:[s.default],initialView:"timelineDay",views:{timeline:{component:N,usesMinMaxTime:!0,eventResizableFromStart:!0},timelineDay:{type:"timeline",duration:{days:1}},timelineWeek:{type:"timeline",duration:{weeks:1}},timelineMonth:{type:"timeline",duration:{months:1}},timelineYear:{type:"timeline",duration:{years:1}}}}),B={__proto__:null,TimelineView:N,buildSlatCols:O,TimelineLane:L,TimelineLaneBg:M,TimelineHeader:w,TimelineSlats:k,buildTimelineDateProfile:c,TimelineCoords:b,coordToCss:R,coordsToCss:y,TimelineLaneSlicer:T,TimelineHeaderRows:S};return t.globalPlugins.push(F),e.Internal=B,e.default=F,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.PremiumCommon,FullCalendar.Internal,FullCalendar.Preact,FullCalendar.ScrollGrid.Internal); | ||
FullCalendar.Timeline=function(e,t,n,i,r){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}var s=l(n);i.config.MAX_TIMELINE_SLOTS=1e3;const a=[{years:1},{months:1},{days:1},{hours:1},{minutes:30},{minutes:15},{minutes:10},{minutes:5},{minutes:1},{seconds:30},{seconds:15},{seconds:10},{seconds:5},{seconds:1},{milliseconds:500},{milliseconds:100},{milliseconds:10},{milliseconds:1}];function o(e,t,n,r){let l={labelInterval:n.slotLabelInterval,slotDuration:n.slotDuration};!function(e,t,n){const{currentRange:r}=t;if(e.labelInterval){n.countDurationsBetween(r.start,r.end,e.labelInterval)>i.config.MAX_TIMELINE_SLOTS&&(console.warn("slotLabelInterval results in too many cells"),e.labelInterval=null)}if(e.slotDuration){n.countDurationsBetween(r.start,r.end,e.slotDuration)>i.config.MAX_TIMELINE_SLOTS&&(console.warn("slotDuration results in too many cells"),e.slotDuration=null)}if(e.labelInterval&&e.slotDuration){const t=i.wholeDivideDurations(e.labelInterval,e.slotDuration);(null===t||t<1)&&(console.warn("slotLabelInterval must be a multiple of slotDuration"),e.slotDuration=null)}}(l,e,t),f(l,e,t),function(e,t,n){const{currentRange:r}=t;let{slotDuration:l}=e;if(!l){const s=f(e,t,n);for(let e of a){const t=i.createDuration(e),n=i.wholeDivideDurations(s,t);if(null!==n&&n>1&&n<=6){l=t;break}}if(l){n.countDurationsBetween(r.start,r.end,l)>200&&(l=null)}l||(l=s),e.slotDuration=l}}(l,e,t);let s=n.slotLabelFormat,o=Array.isArray(s)?s:null!=s?[s]:function(e,t,n,r){let l,s;const{labelInterval:a}=e;let o=i.greatestDurationDenominator(a).unit;const c=r.weekNumbers;let d=l=s=null;"week"!==o||c||(o="day");switch(o){case"year":d={year:"numeric"};break;case"month":h("years",t,n)>1&&(d={year:"numeric"}),l={month:"short"};break;case"week":h("years",t,n)>1&&(d={year:"numeric"}),l={week:"narrow"};break;case"day":h("years",t,n)>1?d={year:"numeric",month:"long"}:h("months",t,n)>1&&(d={month:"long"}),c&&(l={week:"short"}),s={weekday:"narrow",day:"numeric"};break;case"hour":c&&(d={week:"short"}),h("days",t,n)>1&&(l={weekday:"short",day:"numeric",month:"numeric",omitCommas:!0}),s={hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"short"};break;case"minute":i.asRoughMinutes(a)/60>=6?(d={hour:"numeric",meridiem:"short"},l=e=>":"+i.padStart(e.date.minute,2)):d={hour:"numeric",minute:"numeric",meridiem:"short"};break;case"second":i.asRoughSeconds(a)/60>=6?(d={hour:"numeric",minute:"2-digit",meridiem:"lowercase"},l=e=>":"+i.padStart(e.date.second,2)):d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"};break;case"millisecond":d={hour:"numeric",minute:"2-digit",second:"2-digit",meridiem:"lowercase"},l=e=>"."+i.padStart(e.millisecond,3)}return[].concat(d||[],l||[],s||[])}(l,e,t,n);l.headerFormats=o.map(e=>i.createFormatter(e)),l.isTimeScale=Boolean(l.slotDuration.milliseconds);let u=null;if(!l.isTimeScale){const e=i.greatestDurationDenominator(l.slotDuration).unit;/year|month|week/.test(e)&&(u=e)}l.largeUnit=u,l.emphasizeWeeks=1===i.asCleanDays(l.slotDuration)&&h("weeks",e,t)>=2&&!n.businessHours;let g,p,v=n.snapDuration;v&&(g=i.createDuration(v),p=i.wholeDivideDurations(l.slotDuration,g)),null==p&&(g=l.slotDuration,p=1),l.snapDuration=g,l.snapsPerSlot=p;let S=i.asRoughMs(e.slotMaxTime)-i.asRoughMs(e.slotMinTime),R=c(e.renderRange.start,l,t),D=c(e.renderRange.end,l,t);l.isTimeScale&&(R=t.add(R,e.slotMinTime),D=t.add(i.addDays(D,-1),e.slotMaxTime)),l.timeWindowMs=S,l.normalizedRange={start:R,end:D};let y=[],w=R;for(;w<D;)d(w,l,e,r)&&y.push(w),w=t.add(w,l.slotDuration);l.slotDates=y;let b=-1,x=0;const W=[],E=[];for(w=R;w<D;)d(w,l,e,r)?(b+=1,W.push(b),E.push(x)):W.push(b+.5),w=t.add(w,l.snapDuration),x+=1;return l.snapDiffToIndex=W,l.snapIndexToDiff=E,l.snapCnt=b+1,l.slotCnt=l.snapCnt/l.snapsPerSlot,l.isWeekStarts=function(e,t){let{slotDates:n,emphasizeWeeks:i}=e,r=null,l=[];for(let e of n){let n=t.computeWeekNumber(e),s=i&&null!==r&&r!==n;r=n,l.push(s)}return l}(l,t),l.cellRows=function(e,t){let n=e.slotDates,r=e.headerFormats,l=r.map(()=>[]),s=i.asCleanDays(e.slotDuration),a=7===s?"week":1===s?"day":null,o=r.map(e=>e.getLargestUnit?e.getLargestUnit():null);for(let s=0;s<n.length;s+=1){let c=n[s],d=e.isWeekStarts[s];for(let n=0;n<r.length;n+=1){let s=r[n],f=l[n],h=f[f.length-1],u=n===r.length-1,g=r.length>1&&!u,p=null,v=o[n]||(u?a:null);if(g){let e=t.format(c,s);h&&h.text===e?h.colspan+=1:p=m(c,e,v)}else if(!h||i.isInt(t.countDurationsBetween(e.normalizedRange.start,c,e.labelInterval))){let e=t.format(c,s);p=m(c,e,v)}else h.colspan+=1;p&&(p.weekStart=d,f.push(p))}}return l}(l,t),l.slotsPerLabel=i.wholeDivideDurations(l.labelInterval,l.slotDuration),l}function c(e,t,n){let r=e;return t.isTimeScale||(r=i.startOfDay(r),t.largeUnit&&(r=n.startOf(r,t.largeUnit))),r}function d(e,t,n,r){if(r.isHiddenDay(e))return!1;if(t.isTimeScale){let r=i.startOfDay(e),l=e.valueOf()-r.valueOf()-i.asRoughMs(n.slotMinTime);return l=(l%864e5+864e5)%864e5,l<t.timeWindowMs}return!0}function f(e,t,n){const{currentRange:r}=t;let{labelInterval:l}=e;if(!l){let t;if(e.slotDuration){for(t of a){const n=i.createDuration(t),r=i.wholeDivideDurations(n,e.slotDuration);if(null!==r&&r<=6){l=n;break}}l||(l=e.slotDuration)}else for(t of a){l=i.createDuration(t);if(n.countDurationsBetween(r.start,r.end,l)>=18)break}e.labelInterval=l}return l}function h(e,t,n){let r=t.currentRange,l=null;return"years"===e?l=n.diffWholeYears(r.start,r.end):"months"===e||"weeks"===e?l=n.diffWholeMonths(r.start,r.end):"days"===e&&(l=i.diffWholeDays(r.start,r.end)),l||0}function m(e,t,n){return{date:e,text:t,rowUnit:n,colspan:1,isWeekStart:!1}}class u extends i.BaseComponent{constructor(){super(...arguments),this.innerElRef=r.createRef()}render(){let{props:e,context:t}=this,{dateEnv:n,options:l,theme:s}=t,{date:a,tDateProfile:o,isEm:c}=e,d=i.getDateMeta(e.date,e.todayRange,e.nowDate,e.dateProfile),f=Object.assign(Object.assign({date:n.toDate(e.date)},d),{view:t.viewApi});return r.createElement(i.ContentContainer,{elTag:"div",elClasses:["fc-flex-column","fc-align-start","fc-cell","fc-timeline-slot","fc-timeline-slot-lane",c?"fc-timeline-slot-em":"",o.isTimeScale?i.isInt(n.countDurationsBetween(o.normalizedRange.start,e.date,o.labelInterval))?"fc-timeline-slot-major":"fc-timeline-slot-minor":"",...e.isDay?i.getDayClassNames(d,s):i.getSlotClassNames(d,s)],elAttrs:{"data-date":n.formatIso(a,{omitTimeZoneOffset:!0,omitTime:!o.isTimeScale})},elStyle:{width:e.width},renderProps:f,generatorName:"slotLaneContent",customGenerator:l.slotLaneContent,classNameGenerator:l.slotLaneClassNames,didMount:l.slotLaneDidMount,willUnmount:l.slotLaneWillUnmount},e=>r.createElement("div",{ref:this.innerElRef,className:"fc-flex-column"},r.createElement(e,{elTag:"div",elClasses:["fc-cell-inner"]})))}componentDidMount(){const e=this.innerElRef.current;this.detachWidth=i.watchWidth(e,e=>{i.setRef(this.props.innerWidthRef,e)})}componentWillUnmount(){this.detachWidth()}}class g extends i.BaseComponent{constructor(){super(...arguments),this.innerWidthRefMap=new i.RefMap(()=>{i.afterSize(this.handleInnerWidths)}),this.handleInnerWidths=()=>{const e=this.innerWidthRefMap.current;let t=0;for(const n of e.values())t=Math.max(t,n);i.setRef(this.props.innerWidthRef,t)}}render(){let{props:e,innerWidthRefMap:t}=this,{tDateProfile:n,slotWidth:i}=e,{slotDates:l,isWeekStarts:s}=n,a=!n.isTimeScale&&!n.largeUnit;return r.createElement("div",{className:"fc-timeline-slots fc-fill fc-flex-row"},l.map((l,o)=>{let c=l.toISOString();return r.createElement(u,{key:c,date:l,dateProfile:e.dateProfile,tDateProfile:n,nowDate:e.nowDate,todayRange:e.todayRange,isEm:s[o],isDay:a,innerWidthRef:t.createRef(c),width:i})}))}}function p(e,t,n){let r=n.countDurationsBetween(t.normalizedRange.start,e,t.snapDuration);if(r<0)return 0;if(r>=t.snapDiffToIndex.length)return t.snapCnt;let l=Math.floor(r),s=t.snapDiffToIndex[l];return i.isInt(s)?s+=r-l:s=Math.ceil(s),s}function v(e,t){return e?t?{right:e.start,width:e.size}:{left:e.start,width:e.size}:{}}function S(e,t){return t?{right:e}:{left:e}}function R(e,t,n,i,r){if(null==i||null==r)return[void 0,void 0,!1];const l=r/e;let s,a;return l>=(n=Math.max(n||0,(i+1)/t,30))?(s=!0,a=l):(s=!1,a=Math.max(n,l)),[a*e,a,s]}function D(e,t,n,r,l){let s=t.add(n.activeRange.start,e);return r.isTimeScale||(s=i.startOfDay(s)),y(s,t,r,l)}function y(e,t,n,r){return function(e,t,n){let r=n.countDurationsBetween(t.normalizedRange.start,e,t.snapDuration);if(r<0)return 0;if(r>=t.snapDiffToIndex.length)return t.snapCnt;let l=Math.floor(r),s=t.snapDiffToIndex[l];i.isInt(s)?s+=r-l:s=Math.ceil(s);return s}(e,n,t)/n.snapsPerSlot*r}function w(e,t,n,i,r){const l={};for(const s of e)l[s.eventRange.instance.instanceId]=b(s,t,n,i,r);return l}function b(e,t,n,i,r){const l=y(e.start,n,i,r);let s=y(e.end,n,i,r)-l;return t&&(s=Math.max(s,t)),{start:l,size:s}}function x(e,t,n){let i=0;for(const r of e){const{instanceId:e}=r.eventRange.instance,l=t[e],s=n.get(e);null!=l&&null!=s&&(i=Math.max(i,l+s))}return i}class W extends i.BaseComponent{render(){let{props:e}=this,t=[].concat(e.eventResizeSegs,e.dateSelectionSegs);return r.createElement("div",{className:"fc-timeline-bg"},this.renderSegs(e.businessHourSegs||[],"non-business"),this.renderSegs(e.bgEventSegs||[],"bg-event"),this.renderSegs(t,"highlight"))}renderSegs(e,t){let{tDateProfile:n,todayRange:l,nowDate:s,slotWidth:a}=this.props,{dateEnv:o,isRtl:c}=this.context;return r.createElement(r.Fragment,null,e.map(e=>{let d;if(null!=a){d=v(b(e,void 0,o,n,a),c)}return r.createElement("div",{key:i.buildEventRangeKey(e.eventRange),className:"fc-timeline-bg-harness",style:d},"bg-event"===t?r.createElement(i.BgEvent,Object.assign({seg:e},i.getSegMeta(e,l,s))):i.renderFill(t))}))}}class E extends i.Slicer{sliceRange(e,t,n,r,l){let s=function(e,t,n){if(!t.isTimeScale&&(e=i.computeVisibleDayRange(e),t.largeUnit)){let i=e;((e={start:n.startOf(e.start,t.largeUnit),end:n.startOf(e.end,t.largeUnit)}).end.valueOf()!==i.end.valueOf()||e.end<=e.start)&&(e={start:e.start,end:n.add(e.end,t.slotDuration)})}return e}(e,r,l),a=[];if(p(s.start,r,l)<p(s.end,r,l)){let e=i.intersectRanges(s,r.normalizedRange);e&&a.push({start:e.start,end:e.end,isStart:e.start.valueOf()===s.start.valueOf()&&d(e.start,r,t,n),isEnd:e.end.valueOf()===s.end.valueOf()&&d(i.addMs(e.end,-1),r,t,n)})}return a}}const M=i.createFormatter({hour:"numeric",minute:"2-digit",omitZeroMinute:!0,meridiem:"narrow"});class k extends i.BaseComponent{render(){let{props:e,context:t}=this,{options:n}=t;return r.createElement(i.StandardEvent,Object.assign({},e,{elClasses:["fc-timeline-event","fc-h-event",!1===n.eventOverlap?"fc-timeline-event-spacious":""],defaultTimeFormat:M,defaultDisplayEventTime:!e.isTimeScale}))}}class I extends i.BaseComponent{render(){let{props:e}=this,{hiddenSegs:t,resourceId:n,forcedInvisibleMap:l}=e,s=n?{resourceId:n}:{};return r.createElement(i.MoreLinkContainer,{elClasses:["fc-timeline-more-link"],allDayDate:null,segs:t,hiddenSegs:t,dateProfile:e.dateProfile,todayRange:e.todayRange,extraDateSpan:s,popoverContent:()=>r.createElement(r.Fragment,null,t.map(t=>{let n=t.eventRange.instance.instanceId;return r.createElement("div",{key:n,style:{visibility:l[n]?"hidden":""}},r.createElement(k,Object.assign({isTimeScale:e.isTimeScale,seg:t,isDragging:!1,isResizing:!1,isDateSelecting:!1,isSelected:n===e.eventSelection},i.getSegMeta(t,e.todayRange,e.nowDate))))}))},e=>r.createElement(e,{elTag:"div",elClasses:["fc-timeline-more-link-inner","fc-sticky-x"]}))}}class C extends r.Component{constructor(){super(...arguments),this.rootElRef=r.createRef()}render(){const{props:e}=this;return r.createElement("div",{className:"fc-abs",style:e.style,ref:this.rootElRef},e.children)}componentDidMount(){const e=this.rootElRef.current;this.detachHeight=i.watchHeight(e,e=>{i.setRef(this.props.heightRef,e)})}componentWillUnmount(){this.detachHeight()}}class T extends i.BaseComponent{constructor(){super(...arguments),this.sortEventSegs=i.memoize(i.sortEventSegs),this.segHeightRefMap=new i.RefMap(()=>{i.afterSize(this.handleSegHeights)}),this.moreLinkHeightRefMap=new i.RefMap(()=>{i.afterSize(this.handleMoreLinkHeights)}),this.slicer=new E,this.handleMoreLinkHeights=()=>{this.setState({moreLinkHeightRev:this.moreLinkHeightRefMap.rev})},this.handleSegHeights=()=>{this.setState({segHeightRev:this.segHeightRefMap.rev})}}render(){let{props:e,context:t,segHeightRefMap:n}=this,{options:l}=t,{dateProfile:s,tDateProfile:a}=e,o=this.slicer.sliceProps(e,s,a.isTimeScale?null:e.nextDayThreshold,t,s,t.dateProfileGenerator,a,t.dateEnv),c=(o.eventDrag?o.eventDrag.segs:null)||(o.eventResize?o.eventResize.segs:null)||[],d=this.sortEventSegs(o.fgEventSegs,l.eventOrder),f=null!=e.slotWidth?w(d,l.eventMinWidth,t.dateEnv,a,e.slotWidth):{},[h,m,u,g]=function(e,t,n,r,l){let s=[];for(let i=0;i<e.length;i+=1){let r=e[i],l=r.eventRange.instance.instanceId,a=n.get(l),o=t[l];null!=a&&null!=o&&s.push({index:i,seg:r,span:{start:o.start,end:o.start+o.size},thickness:a})}let a=new i.SegHierarchy;null!=r&&(a.strictOrder=r),null!=l&&(a.maxStackCnt=l);let o=a.addSegs(s),c=i.groupIntersectingEntries(o),d=c.map((t,n)=>({index:e.length+n,segGroup:t,span:t.span,thickness:1}));a.maxStackCnt=-1,a.addSegs(d);let f=a.toRects(),h={},m={};for(let e of f){const{seg:t,segGroup:n}=e;t?h[t.eventRange.instance.instanceId]=e.levelCoord:m[n.key]=e.levelCoord}return[h,x(e,h,n),c,m]}(d,f,n.current,l.eventOrderStrict,l.eventMaxStack),p=function(e,t,n){let i=0;for(const r of e){const e=t[r.key],l=n.get(r.key);null!=e&&null!=l&&(i=Math.max(i,e+l))}return i}(u,g,this.moreLinkHeightRefMap.current),v=Math.max(p,m),S=(o.eventDrag?o.eventDrag.affectedInstances:null)||(o.eventResize?o.eventResize.affectedInstances:null)||{};return r.createElement(r.Fragment,null,r.createElement(W,{tDateProfile:a,nowDate:e.nowDate,todayRange:e.todayRange,bgEventSegs:o.bgEventSegs,businessHourSegs:o.businessHourSegs,dateSelectionSegs:o.dateSelectionSegs,eventResizeSegs:o.eventResize?o.eventResize.segs:[],slotWidth:e.slotWidth}),r.createElement("div",{className:["fc-timeline-events","fc-content-box",!1===l.eventOverlap?"fc-timeline-events-overlap-disabled":"fc-timeline-events-overlap-enabled"].join(" "),style:{height:v}},this.renderFgSegs(d,f,h,S,u,g,!1,!1,!1),this.renderFgSegs(c,e.slotWidth?w(c,l.eventMinWidth,t.dateEnv,a,e.slotWidth):{},h,{},[],{},Boolean(o.eventDrag),Boolean(o.eventResize),!1)))}renderFgSegs(e,t,n,l,s,a,o,c,d){let{props:f,context:h,segHeightRefMap:m,moreLinkHeightRefMap:u}=this,g=o||c||d;return r.createElement(r.Fragment,null,e.map(e=>{const{instanceId:s}=e.eventRange.instance,a=n[s],u=t[s],p=g||u&&null!=a&&!l[s];return r.createElement(C,{key:s,style:Object.assign({visibility:p?"":"hidden",top:a||0},v(u,h.isRtl)),heightRef:g?void 0:m.createRef(s)},r.createElement(k,Object.assign({isTimeScale:f.tDateProfile.isTimeScale,seg:e,isDragging:o,isResizing:c,isDateSelecting:d,isSelected:s===f.eventSelection},i.getSegMeta(e,f.todayRange,f.nowDate))))}),s.map(e=>r.createElement(C,{key:e.key,style:Object.assign({top:a[e.key]||0},v({start:e.span.start,size:e.span.end-e.span.start},h.isRtl)),heightRef:u.createRef(e.key)},r.createElement(I,{hiddenSegs:e.segs,dateProfile:f.dateProfile,nowDate:f.nowDate,todayRange:f.todayRange,isTimeScale:f.tDateProfile.isTimeScale,eventSelection:f.eventSelection,resourceId:f.resourceId,forcedInvisibleMap:l}))))}}class P extends i.BaseComponent{constructor(){super(...arguments),this.refineRenderProps=i.memoizeObjArg(H),this.buildCellNavLinkAttrs=i.memoize(z),this.innerElRef=r.createRef()}render(){let{props:e,context:t}=this,{dateEnv:n,options:l}=t,{cell:s,dateProfile:a,tDateProfile:o}=e,c=i.getDateMeta(s.date,e.todayRange,e.nowDate,a),d=this.refineRenderProps({level:e.rowLevel,dateMarker:s.date,text:s.text,dateEnv:t.dateEnv,viewApi:t.viewApi});return r.createElement(i.ContentContainer,{elTag:"div",elClasses:["fc-timeline-slot-label","fc-timeline-slot",s.isWeekStart?"fc-timeline-slot-em":"","fc-header-cell","fc-cell","fc-flex-column","fc-justify-center",e.isCentered?"fc-align-center":"fc-align-start",..."time"===s.rowUnit?i.getSlotClassNames(c,t.theme):i.getDayClassNames(c,t.theme)],elAttrs:{"data-date":n.formatIso(s.date,{omitTime:!o.isTimeScale,omitTimeZoneOffset:!0})},elStyle:{width:null!=e.slotWidth?e.slotWidth*s.colspan:void 0},renderProps:d,generatorName:"slotLabelContent",customGenerator:l.slotLabelContent,defaultGenerator:L,classNameGenerator:l.slotLabelClassNames,didMount:l.slotLabelDidMount,willUnmount:l.slotLabelWillUnmount},n=>r.createElement("div",{ref:this.innerElRef,className:["fc-flex-column",e.isSticky?"fc-sticky-x":""].join(" ")},r.createElement(n,{elTag:"a",elClasses:["fc-cell-inner","fc-padding-md"],elAttrs:this.buildCellNavLinkAttrs(t,s.date,s.rowUnit)})))}componentDidMount(){const{props:e}=this,t=this.innerElRef.current;this.detachSize=i.watchSize(t,(n,r)=>{i.setRef(e.innerWidthRef,n),i.setRef(e.innerHeightRef,r),t.style.left=t.style.right=e.isCentered&&e.isSticky?`calc(50% - ${n/2}px)`:""})}componentWillUnmount(){this.detachSize()}}function z(e,t,n){return n&&"time"!==n?i.buildNavLinkAttrs(e,t,n):{}}function L(e){return e.text}function H(e){return{level:e.level,date:e.dateEnv.toDate(e.dateMarker),view:e.viewApi,text:e.text}}class N extends i.BaseComponent{constructor(){super(...arguments),this.innerWidthRefMap=new i.RefMap(()=>{i.afterSize(this.handleInnerWidths)}),this.innerHeightRefMap=new i.RefMap(()=>{i.afterSize(this.handleInnerHeights)}),this.handleInnerWidths=()=>{const e=this.innerWidthRefMap.current;let t=0;for(const n of e.values())t=Math.max(t,n);i.setRef(this.props.innerWidthRef,t)},this.handleInnerHeights=()=>{const e=this.innerHeightRefMap.current;let t=0;for(const n of e.values())t=Math.max(t,n);i.setRef(this.props.innerHeighRef,t)}}render(){const{props:e,innerWidthRefMap:t,innerHeightRefMap:n}=this,i=!(e.tDateProfile.isTimeScale&&e.isLastRow),l=!e.isLastRow;return r.createElement("div",{className:"fc-row",style:{height:e.height}},e.cells.map(s=>{const a=s.rowUnit+":"+s.date.toISOString();return r.createElement(P,{key:a,cell:s,rowLevel:e.rowLevel,dateProfile:e.dateProfile,tDateProfile:e.tDateProfile,todayRange:e.todayRange,nowDate:e.nowDate,isCentered:i,isSticky:l,innerWidthRef:t.createRef(a),innerHeightRef:n.createRef(a),slotWidth:e.slotWidth})}))}}class O extends i.BaseComponent{render(){const{props:e,context:t}=this;return r.createElement("div",{className:"fc-timeline-now-indicator-container"},r.createElement(i.NowIndicatorContainer,{elClasses:["fc-timeline-now-indicator-line"],elStyle:null!=e.slotWidth?S(y(e.nowDate,t.dateEnv,e.tDateProfile,e.slotWidth),t.isRtl):{},isAxis:!1,date:e.nowDate}))}}class B extends i.BaseComponent{render(){const{props:e,context:t}=this;return r.createElement("div",{className:"fc-timeline-now-indicator-container"},r.createElement(i.NowIndicatorContainer,{elClasses:["fc-timeline-now-indicator-arrow"],elStyle:null!=e.slotWidth?S(y(e.nowDate,t.dateEnv,e.tDateProfile,e.slotWidth),t.isRtl):{},isAxis:!0,date:e.nowDate}))}}class U extends i.DateComponent{constructor(){super(...arguments),this.buildTimelineDateProfile=i.memoize(o),this.computeSlotWidth=i.memoize(R),this.headerScrollerRef=r.createRef(),this.bodyScrollerRef=r.createRef(),this.footerScrollerRef=r.createRef(),this.handleHeaderSlotInnerWidth=e=>{this.headerSlotInnerWidth=e,i.afterSize(this.handleSlotInnerWidths)},this.handleBodySlotInnerWidth=e=>{this.bodySlotInnerWidth=e,i.afterSize(this.handleSlotInnerWidths)},this.handleSlotInnerWidths=()=>{const{state:e}=this,t=Math.max(this.headerSlotInnerWidth,this.bodySlotInnerWidth);e.slotInnerWidth!==t&&this.setState({slotInnerWidth:t})},this.handleScrollerWidth=e=>{this.setState({scrollerWidth:e})},this.handleLeftScrollbarWidth=e=>{this.setState({leftScrollbarWidth:e})},this.handleRightScrollbarWidth=e=>{this.setState({rightScrollbarWidth:e})},this.timeScrollResponder=new i.ScrollResponder(e=>{const{props:t,context:n,tDateProfile:i,slotWidth:r}=this;if(null!=r){const l=D(e,n.dateEnv,t.dateProfile,i,r)+(n.isRtl?-1:1);return this.syncedScroller.scrollTo({x:l}),!0}return!1}),this.handeBodyEl=e=>{this.bodyEl=e,e?this.context.registerInteractiveComponent(this,{el:e}):this.context.unregisterInteractiveComponent(this)}}render(){const{props:e,state:t,context:n}=this,{options:l}=n,s=this.tDateProfile=this.buildTimelineDateProfile(e.dateProfile,n.dateEnv,l,n.dateProfileGenerator),{cellRows:a}=s,o=i.greatestDurationDenominator(s.slotDuration).unit,c=!e.forPrint&&!i.getIsHeightAuto(l),d=!e.forPrint&&i.getStickyHeaderDates(l),f=!e.forPrint&&i.getStickyFooterScrollbar(l),[h,m]=this.computeSlotWidth(s.slotCnt,s.slotsPerLabel,l.slotMinWidth,t.slotInnerWidth,t.scrollerWidth);return this.slotWidth=m,r.createElement(i.NowTimer,{unit:o},(o,u)=>{const p=l.nowIndicator&&null!=m&&i.rangeContainsMarker(e.dateProfile.currentRange,o);return r.createElement(i.ViewContainer,{viewSpec:n.viewSpec,elClasses:["fc-timeline-view","fc-flex-column","fc-border"]},r.createElement(i.Scroller,{horizontal:!0,hideScrollbars:!0,elClassNames:["fc-timeline-header","fc-rowgroup",d?"fc-sticky-header":""],ref:this.headerScrollerRef},r.createElement("div",{className:"fc-rel fc-content-box",style:{width:h,paddingLeft:t.leftScrollbarWidth,paddingRight:t.rightScrollbarWidth}},r.createElement("div",null,a.map((t,n)=>{const i=n===a.length-1;return r.createElement(N,{key:n,dateProfile:e.dateProfile,tDateProfile:s,nowDate:o,todayRange:u,rowLevel:n,isLastRow:i,cells:t,slotWidth:m,innerWidthRef:i?this.handleHeaderSlotInnerWidth:void 0})})),p&&r.createElement(B,{tDateProfile:s,nowDate:o,slotWidth:m}))),r.createElement(i.Scroller,{vertical:c,horizontal:!0,elClassNames:["fc-timeline-body","fc-rowgroup",c?"fc-liquid":""],ref:this.bodyScrollerRef,widthRef:this.handleScrollerWidth,leftScrollbarWidthRef:this.handleLeftScrollbarWidth,rightScrollbarWidthRef:this.handleRightScrollbarWidth},r.createElement("div",{className:"fc-rel fc-grow",style:{width:h},ref:this.handeBodyEl},r.createElement(g,{dateProfile:e.dateProfile,tDateProfile:s,nowDate:o,todayRange:u,innerWidthRef:this.handleBodySlotInnerWidth,slotWidth:m}),r.createElement(T,{dateProfile:e.dateProfile,tDateProfile:s,nowDate:o,todayRange:u,nextDayThreshold:l.nextDayThreshold,eventStore:e.eventStore,eventUiBases:e.eventUiBases,businessHours:e.businessHours,dateSelection:e.dateSelection,eventDrag:e.eventDrag,eventResize:e.eventResize,eventSelection:e.eventSelection,slotWidth:m}),p&&r.createElement(O,{tDateProfile:s,nowDate:o,slotWidth:m}))),f&&r.createElement(i.Scroller,{ref:this.footerScrollerRef,horizontal:!0},r.createElement("div",{style:{width:h}})))})}componentDidMount(){const{context:e}=this,{options:t}=e,n=i.getScrollerSyncerClass(this.context.pluginHooks);this.syncedScroller=new n(!0),this.updateSyncedScroller(),e.emitter.on("_timeScrollRequest",this.timeScrollResponder.handleScroll),this.timeScrollResponder.handleScroll(t.scrollTime)}componentDidUpdate(e){const{options:t}=this.context;this.updateSyncedScroller(),e.dateProfile!==this.props.dateProfile&&t.scrollTimeReset?this.timeScrollResponder.handleScroll(t.scrollTime):this.timeScrollResponder.drain()}componentWillUnmount(){this.syncedScroller.destroy(),this.context.emitter.off("_timeScrollRequest",this.timeScrollResponder.handleScroll)}updateSyncedScroller(){this.syncedScroller.handleChildren([this.headerScrollerRef.current,this.bodyScrollerRef.current,this.footerScrollerRef.current],this.context.isRtl)}queryHit(e,t,n,r){const{props:l,context:s,tDateProfile:a,slotWidth:o}=this,{dateEnv:c}=s;if(o){const t=s.isRtl?n-e:e,d=Math.floor(t/o),f=(t-d*o)/o,h=Math.floor(f*a.snapsPerSlot);let m,u,g=c.add(a.slotDates[d],i.multiplyDuration(a.snapDuration,h)),p=c.add(g,a.snapDuration),v=o/a.snapsPerSlot,S=d*o+v*h,R=S+v;return s.isRtl?(m=n-R,u=n-S):(m=S,u=R),{dateProfile:l.dateProfile,dateSpan:{range:{start:g,end:p},allDay:!a.isTimeScale},rect:{left:m,right:u,top:0,bottom:r},dayEl:this.bodyEl.querySelectorAll(".fc-timeline-slot")[d],layer:0}}return null}}i.injectStyles('.fc-timeline-slots{z-index:1}.fc-timeline-slot-minor{border-style:dotted}.fc-timeline-now-indicator-container{bottom:0;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:4}.fc-timeline-now-indicator-arrow,.fc-timeline-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;pointer-events:none;position:absolute;top:0}.fc-timeline-now-indicator-arrow{border-left-color:transparent;border-right-color:transparent;border-width:6px 5px 0;margin:0 -5px}.fc-timeline-now-indicator-line{border-width:0 0 0 1px;bottom:0}.fc-timeline-events{z-index:3}.fc-timeline-events-overlap-enabled{padding-bottom:10px}.fc-timeline-event{border-radius:0;font-size:var(--fc-small-font-size);margin-bottom:1px;z-index:1}.fc-timeline-event.fc-event-mirror{z-index:2}.fc-direction-ltr .fc-timeline-event.fc-event-end{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end{margin-left:1px}.fc-timeline-event-spacious{margin-bottom:0;padding-bottom:5px;padding-top:5px}.fc-timeline-event .fc-event-inner{align-items:center;display:flex;flex-direction:row;padding:2px 1px}.fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-color:transparent #000;border-style:solid;border-width:5px;content:"";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-right:0}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px}.fc-timeline-more-link{align-items:flex-start;background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;display:flex;flex-direction:column;font-size:var(--fc-small-font-size);padding:1px}.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-more-link-inner{padding:2px}.fc-timeline-bg{bottom:0;left:0;position:absolute;right:0;top:0;z-index:2}.fc-timeline-bg .fc-non-business{z-index:1}.fc-timeline-bg .fc-bg-event{z-index:2}.fc-timeline-bg .fc-highlight{z-index:3}.fc-timeline-bg-harness{bottom:0;position:absolute;top:0}');var A=t.createPlugin({name:"@fullcalendar/timeline",premiumReleaseDate:"2024-10-01",deps:[s.default],initialView:"timelineDay",views:{timeline:{component:U,usesMinMaxTime:!0,eventResizableFromStart:!0},timelineDay:{type:"timeline",duration:{days:1}},timelineWeek:{type:"timeline",duration:{weeks:1}},timelineMonth:{type:"timeline",duration:{months:1}},timelineYear:{type:"timeline",duration:{years:1}}}}),F={__proto__:null,TimelineView:U,TimelineLane:T,TimelineLaneBg:W,TimelineSlats:g,buildTimelineDateProfile:o,createVerticalStyle:function(e){if(e)return{top:e.start,height:e.size}},createHorizontalStyle:function(e,t){if(e)return{[t?"right":"left"]:e.start,width:e.size}},computeSlotWidth:R,timeToCoord:D,coordToCss:function(e,t){return null===e?{left:"",right:""}:t?{right:e,left:""}:{left:e,right:""}},coordsToCss:function(e,t){return e?t?{right:e.start,left:-e.end}:{left:e.start,right:-e.end}:{left:"",right:""}},TimelineLaneSlicer:E,TimelineHeaderRow:N,TimelineNowIndicatorArrow:B,TimelineNowIndicatorLine:O};return t.globalPlugins.push(A),e.Internal=F,e.default=A,Object.defineProperty(e,"__esModule",{value:!0}),e}({},FullCalendar,FullCalendar.PremiumCommon,FullCalendar.Internal,FullCalendar.Preact); |
@@ -6,7 +6,6 @@ import { createPlugin } from '@fullcalendar/core/index.js'; | ||
import '@fullcalendar/core/preact.js'; | ||
import '@fullcalendar/scrollgrid/internal.js'; | ||
var index = createPlugin({ | ||
name: '@fullcalendar/timeline', | ||
premiumReleaseDate: '2024-07-12', | ||
premiumReleaseDate: '2024-10-01', | ||
deps: [premiumCommonPlugin], | ||
@@ -13,0 +12,0 @@ initialView: 'timelineDay', |
@@ -1,5 +0,39 @@ | ||
import { DateRange, DateMarker, DateProfile, DateEnv, BaseOptionsRefined, DateProfileGenerator, PositionCache, SegSpan, DateComponent, ViewProps, Seg, Slicer, EventStore, EventUiHash, DateSpan, EventInteractionState, BaseComponent, ScrollRequest } from '@fullcalendar/core/internal'; | ||
import { createElement, RefObject, VNode } from '@fullcalendar/core/preact'; | ||
import { DateComponent, ViewProps, Hit, DateRange, DateMarker, DateProfile, DateEnv, BaseOptionsRefined, DateProfileGenerator, Seg, Slicer, EventStore, EventUiHash, DateSpan, EventInteractionState, BaseComponent, SegGroup, SegSpan } from '@fullcalendar/core/internal'; | ||
import { createElement, Ref } from '@fullcalendar/core/preact'; | ||
import { Duration, CssDimValue } from '@fullcalendar/core'; | ||
interface TimelineViewState { | ||
scrollerWidth?: number; | ||
leftScrollbarWidth?: number; | ||
rightScrollbarWidth?: number; | ||
slotInnerWidth?: number; | ||
} | ||
declare class TimelineView extends DateComponent<ViewProps, TimelineViewState> { | ||
private buildTimelineDateProfile; | ||
private computeSlotWidth; | ||
private headerScrollerRef; | ||
private bodyScrollerRef; | ||
private footerScrollerRef; | ||
private tDateProfile?; | ||
private bodyEl?; | ||
private slotWidth?; | ||
private headerSlotInnerWidth?; | ||
private bodySlotInnerWidth?; | ||
private syncedScroller; | ||
render(): createElement.JSX.Element; | ||
componentDidMount(): void; | ||
componentDidUpdate(prevProps: ViewProps): void; | ||
componentWillUnmount(): void; | ||
handleHeaderSlotInnerWidth: (innerWidth: number) => void; | ||
handleBodySlotInnerWidth: (innerWidth: number) => void; | ||
handleSlotInnerWidths: () => void; | ||
handleScrollerWidth: (scrollerWidth: number) => void; | ||
handleLeftScrollbarWidth: (leftScrollbarWidth: number) => void; | ||
handleRightScrollbarWidth: (rightScrollbarWidth: number) => void; | ||
updateSyncedScroller(): void; | ||
private timeScrollResponder; | ||
handeBodyEl: (el: HTMLElement | null) => void; | ||
queryHit(positionLeft: number, positionTop: number, elWidth: number, elHeight: number): Hit; | ||
} | ||
interface TimelineDateProfile { | ||
@@ -23,5 +57,5 @@ labelInterval: Duration; | ||
slotCnt: number; | ||
cellRows: TimelineHeaderCell[][]; | ||
cellRows: TimelineHeaderCellData[][]; | ||
} | ||
interface TimelineHeaderCell { | ||
interface TimelineHeaderCellData { | ||
date: DateMarker; | ||
@@ -35,50 +69,2 @@ text: string; | ||
declare class TimelineCoords { | ||
slatRootEl: HTMLElement; | ||
dateProfile: DateProfile; | ||
private tDateProfile; | ||
private dateEnv; | ||
isRtl: boolean; | ||
outerCoordCache: PositionCache; | ||
innerCoordCache: PositionCache; | ||
constructor(slatRootEl: HTMLElement, // okay to expose? | ||
slatEls: HTMLElement[], dateProfile: DateProfile, tDateProfile: TimelineDateProfile, dateEnv: DateEnv, isRtl: boolean); | ||
isDateInRange(date: DateMarker): boolean; | ||
dateToCoord(date: DateMarker): number; | ||
rangeToCoords(range: DateRange): SegSpan; | ||
durationToCoord(duration: Duration): number; | ||
coordFromLeft(coord: number): number; | ||
computeDateSnapCoverage(date: DateMarker): number; | ||
} | ||
declare function coordToCss(hcoord: number | null, isRtl: boolean): { | ||
left: CssDimValue; | ||
right: CssDimValue; | ||
}; | ||
declare function coordsToCss(hcoords: SegSpan | null, isRtl: boolean): { | ||
left: CssDimValue; | ||
right: CssDimValue; | ||
}; | ||
interface TimelineViewState { | ||
slatCoords: TimelineCoords | null; | ||
slotCushionMaxWidth: number | null; | ||
} | ||
declare class TimelineView extends DateComponent<ViewProps, TimelineViewState> { | ||
private buildTimelineDateProfile; | ||
private scrollGridRef; | ||
state: { | ||
slatCoords: any; | ||
slotCushionMaxWidth: any; | ||
}; | ||
render(): createElement.JSX.Element; | ||
handleSlatCoords: (slatCoords: TimelineCoords | null) => void; | ||
handleScrollLeftRequest: (scrollLeft: number) => void; | ||
handleMaxCushionWidth: (slotCushionMaxWidth: any) => void; | ||
computeFallbackSlotMinWidth(tDateProfile: TimelineDateProfile): number; | ||
} | ||
declare function buildSlatCols(tDateProfile: TimelineDateProfile, slotMinWidth?: number): { | ||
span: number; | ||
minWidth: number; | ||
}[]; | ||
interface TimelineLaneSeg extends Seg { | ||
@@ -97,89 +83,114 @@ start: DateMarker; | ||
interface TimelineSegPlacement { | ||
seg: TimelineLaneSeg | TimelineLaneSeg[]; | ||
hcoords: SegSpan | null; | ||
top: number | null; | ||
interface TimelineSegHorizontals { | ||
start: number; | ||
size: number; | ||
} | ||
interface TimelineLaneProps extends TimelineLaneCoreProps { | ||
onHeightChange?: (innerEl: HTMLElement, isStable: boolean) => void; | ||
} | ||
interface TimelineLaneCoreProps { | ||
interface TimelineLaneProps { | ||
dateProfile: DateProfile; | ||
tDateProfile: TimelineDateProfile; | ||
nowDate: DateMarker; | ||
todayRange: DateRange; | ||
dateProfile: DateProfile; | ||
tDateProfile: TimelineDateProfile; | ||
nextDayThreshold: Duration; | ||
businessHours: EventStore | null; | ||
eventStore: EventStore | null; | ||
eventUiBases: EventUiHash; | ||
businessHours: EventStore | null; | ||
dateSelection: DateSpan | null; | ||
eventSelection: string; | ||
eventDrag: EventInteractionState | null; | ||
eventResize: EventInteractionState | null; | ||
timelineCoords: TimelineCoords | null; | ||
eventSelection: string; | ||
resourceId?: string; | ||
syncParentMinHeight?: boolean; | ||
slotWidth: number | undefined; | ||
} | ||
interface TimelineLaneState { | ||
eventInstanceHeights: { | ||
[instanceId: string]: number; | ||
}; | ||
moreLinkHeights: { | ||
[isoStr: string]: number; | ||
}; | ||
segHeightRev?: string; | ||
moreLinkHeightRev?: string; | ||
} | ||
declare class TimelineLane extends BaseComponent<TimelineLaneProps, TimelineLaneState> { | ||
private sortEventSegs; | ||
private segHeightRefMap; | ||
private moreLinkHeightRefMap; | ||
private slicer; | ||
private sortEventSegs; | ||
private harnessElRefs; | ||
private moreElRefs; | ||
private innerElRef; | ||
state: TimelineLaneState; | ||
render(): createElement.JSX.Element; | ||
componentDidMount(): void; | ||
componentDidUpdate(prevProps: TimelineLaneProps, prevState: TimelineLaneState): void; | ||
componentWillUnmount(): void; | ||
handleResize: (isForced: boolean) => void; | ||
updateSize(): void; | ||
renderFgSegs(segPlacements: TimelineSegPlacement[], isForcedInvisible: { | ||
renderFgSegs(segs: TimelineLaneSeg[], segHorizontals: { | ||
[instanceId: string]: TimelineSegHorizontals; | ||
}, segTops: { | ||
[instanceId: string]: number; | ||
}, forcedInvisibleMap: { | ||
[instanceId: string]: any; | ||
}, hiddenGroups: SegGroup[], hiddenGroupTops: { | ||
[key: string]: number; | ||
}, isDragging: boolean, isResizing: boolean, isDateSelecting: boolean): createElement.JSX.Element; | ||
private handleMoreLinkHeights; | ||
private handleSegHeights; | ||
} | ||
interface TimelineLaneBgProps { | ||
tDateProfile: TimelineDateProfile; | ||
nowDate: DateMarker; | ||
todayRange: DateRange; | ||
bgEventSegs: TimelineLaneSeg[] | null; | ||
businessHourSegs: TimelineLaneSeg[] | null; | ||
bgEventSegs: TimelineLaneSeg[] | null; | ||
dateSelectionSegs: TimelineLaneSeg[]; | ||
eventResizeSegs: TimelineLaneSeg[]; | ||
timelineCoords: TimelineCoords | null; | ||
todayRange: DateRange; | ||
nowDate: DateMarker; | ||
slotWidth: number | undefined; | ||
} | ||
declare class TimelineLaneBg extends BaseComponent<TimelineLaneBgProps> { | ||
render(): createElement.JSX.Element; | ||
renderSegs(segs: TimelineLaneSeg[], timelineCoords: TimelineCoords | null, fillType: string): createElement.JSX.Element; | ||
renderSegs(segs: TimelineLaneSeg[], fillType: string): createElement.JSX.Element; | ||
} | ||
interface TimelineHeaderProps { | ||
interface TimelineSlatsProps { | ||
dateProfile: DateProfile; | ||
tDateProfile: TimelineDateProfile; | ||
clientWidth: number | null; | ||
clientHeight: number | null; | ||
tableMinWidth: CssDimValue; | ||
tableColGroupNode: VNode; | ||
slatCoords: TimelineCoords; | ||
rowInnerHeights?: number[]; | ||
onMaxCushionWidth?: (number: any) => void; | ||
nowDate: DateMarker; | ||
todayRange: DateRange; | ||
slotWidth: number | undefined; | ||
innerWidthRef?: Ref<number>; | ||
} | ||
declare class TimelineHeader extends BaseComponent<TimelineHeaderProps> { | ||
rootElRef: RefObject<HTMLDivElement>; | ||
declare class TimelineSlats extends BaseComponent<TimelineSlatsProps> { | ||
private innerWidthRefMap; | ||
render(): createElement.JSX.Element; | ||
componentDidMount(): void; | ||
componentDidUpdate(): void; | ||
updateSize(): void; | ||
computeMaxCushionWidth(): number; | ||
handleInnerWidths: () => void; | ||
} | ||
interface TimelineSlatsContentProps { | ||
interface CoordRange { | ||
start: number; | ||
size: number; | ||
} | ||
declare function createVerticalStyle(props: { | ||
start: number; | ||
size: number; | ||
} | undefined): { | ||
top: number; | ||
height: number; | ||
} | undefined; | ||
declare function createHorizontalStyle(props: { | ||
start: number; | ||
size: number; | ||
} | undefined, isRtl: boolean): { | ||
left: number; | ||
width: number; | ||
} | { | ||
right: number; | ||
width: number; | ||
} | undefined; | ||
declare function computeSlotWidth(slatCnt: number, slatsPerLabel: number, slatMinWidth: number | undefined, labelInnerWidth: number | undefined, viewportWidth: number | undefined): [ | ||
canvasWidth: number | undefined, | ||
slatWidth: number | undefined, | ||
slatLiquid: boolean | ||
]; | ||
declare function timeToCoord(// pixels | ||
time: Duration, dateEnv: DateEnv, dateProfile: DateProfile, tDateProfile: TimelineDateProfile, slowWidth: number): number; | ||
declare function coordToCss(hcoord: number | null, isRtl: boolean): { | ||
left: CssDimValue; | ||
right: CssDimValue; | ||
}; | ||
declare function coordsToCss(hcoords: SegSpan | null, isRtl: boolean): { | ||
left: CssDimValue; | ||
right: CssDimValue; | ||
}; | ||
interface TimelineHeaderRowProps { | ||
dateProfile: DateProfile; | ||
@@ -189,47 +200,36 @@ tDateProfile: TimelineDateProfile; | ||
todayRange: DateRange; | ||
rowLevel: number; | ||
isLastRow: boolean; | ||
cells: TimelineHeaderCellData[]; | ||
innerHeighRef?: Ref<number>; | ||
innerWidthRef?: Ref<number>; | ||
slotWidth: number | undefined; | ||
height?: number; | ||
} | ||
declare class TimelineHeaderRow extends BaseComponent<TimelineHeaderRowProps> { | ||
private innerWidthRefMap; | ||
private innerHeightRefMap; | ||
render(): createElement.JSX.Element; | ||
handleInnerWidths: () => void; | ||
handleInnerHeights: () => void; | ||
} | ||
interface TimelineSlatsProps extends TimelineSlatsContentProps { | ||
clientWidth: number | null; | ||
tableMinWidth: CssDimValue; | ||
tableColGroupNode: VNode; | ||
onCoords?: (coord: TimelineCoords | null) => void; | ||
onScrollLeftRequest?: (scrollLeft: number) => void; | ||
interface TimelineNowIndicatorArrowProps { | ||
tDateProfile: TimelineDateProfile; | ||
nowDate: DateMarker; | ||
slotWidth: number | undefined; | ||
} | ||
declare class TimelineSlats extends BaseComponent<TimelineSlatsProps> { | ||
private rootElRef; | ||
private cellElRefs; | ||
private coords; | ||
private scrollResponder; | ||
declare class TimelineNowIndicatorArrow extends BaseComponent<TimelineNowIndicatorArrowProps> { | ||
render(): createElement.JSX.Element; | ||
componentDidMount(): void; | ||
componentDidUpdate(prevProps: TimelineSlatsProps): void; | ||
componentWillUnmount(): void; | ||
updateSizing(): void; | ||
handleScrollRequest: (request: ScrollRequest) => boolean; | ||
positionToHit(leftPosition: any): { | ||
dateSpan: { | ||
range: { | ||
start: Date; | ||
end: Date; | ||
}; | ||
allDay: boolean; | ||
}; | ||
dayEl: HTMLTableCellElement; | ||
left: any; | ||
right: any; | ||
}; | ||
} | ||
interface TimelineHeaderRowsProps { | ||
dateProfile: DateProfile; | ||
interface TimelineNowIndicatorLineProps { | ||
tDateProfile: TimelineDateProfile; | ||
nowDate: DateMarker; | ||
todayRange: DateRange; | ||
rowInnerHeights?: number[]; | ||
slotWidth: number | undefined; | ||
} | ||
declare class TimelineHeaderRows extends BaseComponent<TimelineHeaderRowsProps> { | ||
declare class TimelineNowIndicatorLine extends BaseComponent<TimelineNowIndicatorLineProps> { | ||
render(): createElement.JSX.Element; | ||
} | ||
export { TimelineCoords, TimelineDateProfile, TimelineHeader, TimelineHeaderRows, TimelineLane, TimelineLaneBg, TimelineLaneCoreProps, TimelineLaneProps, TimelineLaneSeg, TimelineLaneSlicer, TimelineSlats, TimelineView, buildSlatCols, buildTimelineDateProfile, coordToCss, coordsToCss }; | ||
export { CoordRange, TimelineDateProfile, TimelineHeaderRow, TimelineLane, TimelineLaneBg, TimelineLaneProps, TimelineLaneSeg, TimelineLaneSlicer, TimelineNowIndicatorArrow, TimelineNowIndicatorLine, TimelineSlats, TimelineView, buildTimelineDateProfile, computeSlotWidth, coordToCss, coordsToCss, createHorizontalStyle, createVerticalStyle, timeToCoord }; |
1270
internal.js
@@ -1,5 +0,7 @@ | ||
import { config, createFormatter, greatestDurationDenominator, asCleanDays, createDuration, wholeDivideDurations, asRoughMs, addDays, startOfDay, asRoughSeconds, asRoughMinutes, diffWholeDays, isInt, computeVisibleDayRange, padStart, BaseComponent, memoizeObjArg, memoize, getDateMeta, ContentContainer, getSlotClassNames, getDayClassNames, buildNavLinkAttrs, PositionCache, findDirectChildren, rangeContainsMarker, NowTimer, NowIndicatorContainer, findElements, RefMap, multiplyDuration, SegHierarchy, groupIntersectingEntries, buildIsoString, computeEarliestSegStart, buildEventRangeKey, BgEvent, getSegMeta, renderFill, Slicer, intersectRanges, addMs, StandardEvent, MoreLinkContainer, sortEventSegs, mapHash, isPropsEqual, DateComponent, getStickyHeaderDates, getStickyFooterScrollbar, ViewContainer, renderScrollShim, injectStyles } from '@fullcalendar/core/internal.js'; | ||
import { createElement, Fragment, createRef } from '@fullcalendar/core/preact.js'; | ||
import { ScrollGrid } from '@fullcalendar/scrollgrid/internal.js'; | ||
import { injectStyles, config, createFormatter, greatestDurationDenominator, asCleanDays, createDuration, wholeDivideDurations, asRoughMs, addDays, startOfDay, asRoughSeconds, asRoughMinutes, diffWholeDays, isInt, computeVisibleDayRange, padStart, BaseComponent, getDateMeta, ContentContainer, getDayClassNames, getSlotClassNames, watchWidth, setRef, RefMap, afterSize, SegHierarchy, groupIntersectingEntries, buildEventRangeKey, BgEvent, getSegMeta, renderFill, Slicer, intersectRanges, addMs, StandardEvent, MoreLinkContainer, watchHeight, memoize, sortEventSegs, memoizeObjArg, watchSize, buildNavLinkAttrs, NowIndicatorContainer, DateComponent, ScrollResponder, getIsHeightAuto, getStickyHeaderDates, getStickyFooterScrollbar, NowTimer, rangeContainsMarker, ViewContainer, Scroller, getScrollerSyncerClass, multiplyDuration } from '@fullcalendar/core/internal.js'; | ||
import { createRef, createElement, Fragment, Component } from '@fullcalendar/core/preact.js'; | ||
var css_248z = ".fc-timeline-slots{z-index:1}.fc-timeline-slot-minor{border-style:dotted}.fc-timeline-now-indicator-container{bottom:0;left:0;overflow:hidden;position:absolute;right:0;top:0;z-index:4}.fc-timeline-now-indicator-arrow,.fc-timeline-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;pointer-events:none;position:absolute;top:0}.fc-timeline-now-indicator-arrow{border-left-color:transparent;border-right-color:transparent;border-width:6px 5px 0;margin:0 -5px}.fc-timeline-now-indicator-line{border-width:0 0 0 1px;bottom:0}.fc-timeline-events{z-index:3}.fc-timeline-events-overlap-enabled{padding-bottom:10px}.fc-timeline-event{border-radius:0;font-size:var(--fc-small-font-size);margin-bottom:1px;z-index:1}.fc-timeline-event.fc-event-mirror{z-index:2}.fc-direction-ltr .fc-timeline-event.fc-event-end{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end{margin-left:1px}.fc-timeline-event-spacious{margin-bottom:0;padding-bottom:5px;padding-top:5px}.fc-timeline-event .fc-event-inner{align-items:center;display:flex;flex-direction:row;padding:2px 1px}.fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-color:transparent #000;border-style:solid;border-width:5px;content:\"\";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end) .fc-event-inner:after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start) .fc-event-inner:before{border-right:0}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px}.fc-timeline-more-link{align-items:flex-start;background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;display:flex;flex-direction:column;font-size:var(--fc-small-font-size);padding:1px}.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-more-link-inner{padding:2px}.fc-timeline-bg{bottom:0;left:0;position:absolute;right:0;top:0;z-index:2}.fc-timeline-bg .fc-non-business{z-index:1}.fc-timeline-bg .fc-bg-event{z-index:2}.fc-timeline-bg .fc-highlight{z-index:3}.fc-timeline-bg-harness{bottom:0;position:absolute;top:0}"; | ||
injectStyles(css_248z); | ||
const MIN_AUTO_LABELS = 18; // more than `12` months but less that `24` hours | ||
@@ -443,75 +445,77 @@ const MAX_AUTO_SLOTS_PER_LABEL = 6; // allows 6 10-min slots in an hour | ||
class TimelineHeaderTh extends BaseComponent { | ||
class TimelineSlatCell extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
this.refineRenderProps = memoizeObjArg(refineRenderProps); | ||
this.buildCellNavLinkAttrs = memoize(buildCellNavLinkAttrs); | ||
// ref | ||
this.innerElRef = createRef(); | ||
} | ||
render() { | ||
let { props, context } = this; | ||
let { dateEnv, options } = context; | ||
let { cell, dateProfile, tDateProfile } = props; | ||
// the cell.rowUnit is f'd | ||
// giving 'month' for a 3-day view | ||
// workaround: to infer day, do NOT time | ||
let dateMeta = getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile); | ||
let renderProps = this.refineRenderProps({ | ||
level: props.rowLevel, | ||
dateMarker: cell.date, | ||
text: cell.text, | ||
dateEnv: context.dateEnv, | ||
viewApi: context.viewApi, | ||
}); | ||
return (createElement(ContentContainer, { elTag: "th", elClasses: [ | ||
let { dateEnv, options, theme } = context; | ||
let { date, tDateProfile, isEm } = props; | ||
let dateMeta = getDateMeta(props.date, props.todayRange, props.nowDate, props.dateProfile); | ||
let renderProps = Object.assign(Object.assign({ date: dateEnv.toDate(props.date) }, dateMeta), { view: context.viewApi }); | ||
return (createElement(ContentContainer, { elTag: "div", elClasses: [ | ||
'fc-flex-column', | ||
'fc-align-start', | ||
'fc-cell', | ||
'fc-timeline-slot', | ||
'fc-timeline-slot-label', | ||
cell.isWeekStart && 'fc-timeline-slot-em', | ||
...( // TODO: so slot classnames for week/month/bigger. see note above about rowUnit | ||
cell.rowUnit === 'time' ? | ||
getSlotClassNames(dateMeta, context.theme) : | ||
getDayClassNames(dateMeta, context.theme)), | ||
'fc-timeline-slot-lane', | ||
isEm ? 'fc-timeline-slot-em' : '', | ||
tDateProfile.isTimeScale ? (isInt(dateEnv.countDurationsBetween(// best to do this here? | ||
tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval)) ? | ||
'fc-timeline-slot-major' : | ||
'fc-timeline-slot-minor') : '', | ||
...(props.isDay ? | ||
getDayClassNames(dateMeta, theme) : | ||
getSlotClassNames(dateMeta, theme)), | ||
], elAttrs: { | ||
colSpan: cell.colspan, | ||
'data-date': dateEnv.formatIso(cell.date, { | ||
'data-date': dateEnv.formatIso(date, { | ||
omitTimeZoneOffset: true, | ||
omitTime: !tDateProfile.isTimeScale, | ||
omitTimeZoneOffset: true, | ||
}), | ||
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (createElement("div", { className: "fc-timeline-slot-frame", style: { height: props.rowInnerHeight } }, | ||
createElement(InnerContent, { elTag: "a", elClasses: [ | ||
'fc-timeline-slot-cushion', | ||
'fc-scrollgrid-sync-inner', | ||
props.isSticky && 'fc-sticky', | ||
], elAttrs: this.buildCellNavLinkAttrs(context, cell.date, cell.rowUnit) }))))); | ||
}, elStyle: { | ||
width: props.width, | ||
}, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (createElement("div", { ref: this.innerElRef, className: 'fc-flex-column' }, | ||
createElement(InnerContent, { elTag: "div", elClasses: ['fc-cell-inner'] }))))); | ||
} | ||
componentDidMount() { | ||
const innerEl = this.innerElRef.current; | ||
this.detachWidth = watchWidth(innerEl, (width) => { | ||
setRef(this.props.innerWidthRef, width); | ||
}); | ||
} | ||
componentWillUnmount() { | ||
this.detachWidth(); | ||
} | ||
} | ||
function buildCellNavLinkAttrs(context, cellDate, rowUnit) { | ||
return (rowUnit && rowUnit !== 'time') | ||
? buildNavLinkAttrs(context, cellDate, rowUnit) | ||
: {}; | ||
} | ||
function renderInnerContent(renderProps) { | ||
return renderProps.text; | ||
} | ||
function refineRenderProps(input) { | ||
return { | ||
level: input.level, | ||
date: input.dateEnv.toDate(input.dateMarker), | ||
view: input.viewApi, | ||
text: input.text, | ||
}; | ||
} | ||
class TimelineHeaderRows extends BaseComponent { | ||
class TimelineSlats extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
this.innerWidthRefMap = new RefMap(() => { | ||
afterSize(this.handleInnerWidths); | ||
}); | ||
this.handleInnerWidths = () => { | ||
const innerWidthMap = this.innerWidthRefMap.current; | ||
let max = 0; | ||
for (const innerWidth of innerWidthMap.values()) { | ||
max = Math.max(max, innerWidth); | ||
} | ||
// TODO: check to see if changed before firing ref!? YES. do in other places too | ||
setRef(this.props.innerWidthRef, max); | ||
}; | ||
} | ||
render() { | ||
let { dateProfile, tDateProfile, rowInnerHeights, todayRange, nowDate } = this.props; | ||
let { cellRows } = tDateProfile; | ||
return (createElement(Fragment, null, cellRows.map((rowCells, rowLevel) => { | ||
let isLast = rowLevel === cellRows.length - 1; | ||
let isChrono = tDateProfile.isTimeScale && isLast; // the final row, with times? | ||
let classNames = [ | ||
'fc-timeline-header-row', | ||
isChrono ? 'fc-timeline-header-row-chrono' : '', | ||
]; | ||
return ( // eslint-disable-next-line react/no-array-index-key | ||
createElement("tr", { key: rowLevel, className: classNames.join(' ') }, rowCells.map((cell) => (createElement(TimelineHeaderTh, { key: cell.date.toISOString(), cell: cell, rowLevel: rowLevel, dateProfile: dateProfile, tDateProfile: tDateProfile, todayRange: todayRange, nowDate: nowDate, rowInnerHeight: rowInnerHeights && rowInnerHeights[rowLevel], isSticky: !isLast }))))); | ||
let { props, innerWidthRefMap } = this; | ||
let { tDateProfile, slotWidth } = props; | ||
let { slotDates, isWeekStarts } = tDateProfile; | ||
let isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit; | ||
return (createElement("div", { className: "fc-timeline-slots fc-fill fc-flex-row" }, slotDates.map((slotDate, i) => { | ||
let key = slotDate.toISOString(); | ||
return (createElement(TimelineSlatCell, { key: key, date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isEm: isWeekStarts[i], isDay: isDay, | ||
// ref | ||
innerWidthRef: innerWidthRefMap.createRef(key), | ||
// dimensions | ||
width: slotWidth })); | ||
}))); | ||
@@ -521,71 +525,7 @@ } | ||
class TimelineCoords { | ||
constructor(slatRootEl, // okay to expose? | ||
slatEls, dateProfile, tDateProfile, dateEnv, isRtl) { | ||
this.slatRootEl = slatRootEl; | ||
this.dateProfile = dateProfile; | ||
this.tDateProfile = tDateProfile; | ||
this.dateEnv = dateEnv; | ||
this.isRtl = isRtl; | ||
this.outerCoordCache = new PositionCache(slatRootEl, slatEls, true, // isHorizontal | ||
false); | ||
// for the inner divs within the slats | ||
// used for event rendering and scrollTime, to disregard slat border | ||
this.innerCoordCache = new PositionCache(slatRootEl, findDirectChildren(slatEls, 'div'), true, // isHorizontal | ||
false); | ||
} | ||
isDateInRange(date) { | ||
return rangeContainsMarker(this.dateProfile.currentRange, date); | ||
} | ||
// results range from negative width of area to 0 | ||
dateToCoord(date) { | ||
let { tDateProfile } = this; | ||
let snapCoverage = this.computeDateSnapCoverage(date); | ||
let slotCoverage = snapCoverage / tDateProfile.snapsPerSlot; | ||
let slotIndex = Math.floor(slotCoverage); | ||
slotIndex = Math.min(slotIndex, tDateProfile.slotCnt - 1); | ||
let partial = slotCoverage - slotIndex; | ||
let { innerCoordCache, outerCoordCache } = this; | ||
if (this.isRtl) { | ||
return outerCoordCache.originClientRect.width - (outerCoordCache.rights[slotIndex] - | ||
(innerCoordCache.getWidth(slotIndex) * partial)); | ||
} | ||
return (outerCoordCache.lefts[slotIndex] + | ||
(innerCoordCache.getWidth(slotIndex) * partial)); | ||
} | ||
rangeToCoords(range) { | ||
return { | ||
start: this.dateToCoord(range.start), | ||
end: this.dateToCoord(range.end), | ||
}; | ||
} | ||
durationToCoord(duration) { | ||
let { dateProfile, tDateProfile, dateEnv, isRtl } = this; | ||
let coord = 0; | ||
if (dateProfile) { | ||
let date = dateEnv.add(dateProfile.activeRange.start, duration); | ||
if (!tDateProfile.isTimeScale) { | ||
date = startOfDay(date); | ||
} | ||
coord = this.dateToCoord(date); | ||
// hack to overcome the left borders of non-first slat | ||
if (!isRtl && coord) { | ||
coord += 1; | ||
} | ||
} | ||
return coord; | ||
} | ||
coordFromLeft(coord) { | ||
if (this.isRtl) { | ||
return this.outerCoordCache.originClientRect.width - coord; | ||
} | ||
return coord; | ||
} | ||
// returned value is between 0 and the number of snaps | ||
computeDateSnapCoverage(date) { | ||
return computeDateSnapCoverage(date, this.tDateProfile, this.dateEnv); | ||
} | ||
} | ||
/* | ||
TODO: rename this file! | ||
*/ | ||
// returned value is between 0 and the number of snaps | ||
function computeDateSnapCoverage(date, tDateProfile, dateEnv) { | ||
function computeDateSnapCoverage$1(date, tDateProfile, dateEnv) { | ||
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration); | ||
@@ -610,2 +550,5 @@ if (snapDiff < 0) { | ||
} | ||
/* | ||
TODO: audit!!! | ||
*/ | ||
function coordToCss(hcoord, isRtl) { | ||
@@ -620,2 +563,5 @@ if (hcoord === null) { | ||
} | ||
/* | ||
TODO: audit!!! | ||
*/ | ||
function coordsToCss(hcoords, isRtl) { | ||
@@ -630,214 +576,139 @@ if (!hcoords) { | ||
} | ||
class TimelineHeader extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
this.rootElRef = createRef(); | ||
/* | ||
TODO: DRY up with elsewhere? | ||
*/ | ||
function horizontalsToCss(hcoord, isRtl) { | ||
if (!hcoord) { | ||
return {}; | ||
} | ||
render() { | ||
let { props, context } = this; | ||
// TODO: very repetitive | ||
// TODO: make part of tDateProfile? | ||
let timerUnit = greatestDurationDenominator(props.tDateProfile.slotDuration).unit; | ||
// WORKAROUND: make ignore slatCoords when out of sync with dateProfile | ||
let slatCoords = props.slatCoords && props.slatCoords.dateProfile === props.dateProfile ? props.slatCoords : null; | ||
return (createElement(NowTimer, { unit: timerUnit }, (nowDate, todayRange) => (createElement("div", { className: "fc-timeline-header", ref: this.rootElRef }, | ||
createElement("table", { "aria-hidden": true, className: "fc-scrollgrid-sync-table", style: { minWidth: props.tableMinWidth, width: props.clientWidth } }, | ||
props.tableColGroupNode, | ||
createElement("tbody", null, | ||
createElement(TimelineHeaderRows, { dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, nowDate: nowDate, todayRange: todayRange, rowInnerHeights: props.rowInnerHeights }))), | ||
context.options.nowIndicator && ( | ||
// need to have a container regardless of whether the current view has a visible now indicator | ||
// because apparently removal of the element resets the scroll for some reasons (issue #5351). | ||
// this issue doesn't happen for the timeline body however ( | ||
createElement("div", { className: "fc-timeline-now-indicator-container" }, (slatCoords && slatCoords.isDateInRange(nowDate)) && (createElement(NowIndicatorContainer, { elClasses: ['fc-timeline-now-indicator-arrow'], elStyle: coordToCss(slatCoords.dateToCoord(nowDate), context.isRtl), isAxis: true, date: nowDate })))))))); | ||
if (isRtl) { | ||
return { right: hcoord.start, width: hcoord.size }; | ||
} | ||
componentDidMount() { | ||
this.updateSize(); | ||
else { | ||
return { left: hcoord.start, width: hcoord.size }; | ||
} | ||
componentDidUpdate() { | ||
this.updateSize(); | ||
} | ||
function horizontalCoordToCss(start, isRtl) { | ||
if (isRtl) { | ||
return { right: start }; | ||
} | ||
updateSize() { | ||
if (this.props.onMaxCushionWidth) { | ||
this.props.onMaxCushionWidth(this.computeMaxCushionWidth()); | ||
} | ||
else { | ||
return { left: start }; | ||
} | ||
computeMaxCushionWidth() { | ||
return Math.max(...findElements(this.rootElRef.current, '.fc-timeline-header-row:last-child .fc-timeline-slot-cushion').map((el) => el.getBoundingClientRect().width)); | ||
} | ||
} | ||
class TimelineSlatCell extends BaseComponent { | ||
render() { | ||
let { props, context } = this; | ||
let { dateEnv, options, theme } = context; | ||
let { date, tDateProfile, isEm } = props; | ||
let dateMeta = getDateMeta(props.date, props.todayRange, props.nowDate, props.dateProfile); | ||
let renderProps = Object.assign(Object.assign({ date: dateEnv.toDate(props.date) }, dateMeta), { view: context.viewApi }); | ||
return (createElement(ContentContainer, { elTag: "td", elRef: props.elRef, elClasses: [ | ||
'fc-timeline-slot', | ||
'fc-timeline-slot-lane', | ||
isEm && 'fc-timeline-slot-em', | ||
tDateProfile.isTimeScale ? (isInt(dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, props.date, tDateProfile.labelInterval)) ? | ||
'fc-timeline-slot-major' : | ||
'fc-timeline-slot-minor') : '', | ||
...(props.isDay ? | ||
getDayClassNames(dateMeta, theme) : | ||
getSlotClassNames(dateMeta, theme)), | ||
], elAttrs: { | ||
'data-date': dateEnv.formatIso(date, { | ||
omitTimeZoneOffset: true, | ||
omitTime: !tDateProfile.isTimeScale, | ||
}), | ||
}, renderProps: renderProps, generatorName: "slotLaneContent", customGenerator: options.slotLaneContent, classNameGenerator: options.slotLaneClassNames, didMount: options.slotLaneDidMount, willUnmount: options.slotLaneWillUnmount }, (InnerContent) => (createElement(InnerContent, { elTag: "div" })))); | ||
function createVerticalStyle(props) { | ||
if (props) { | ||
return { | ||
top: props.start, | ||
height: props.size, | ||
}; | ||
} | ||
} | ||
class TimelineSlatsBody extends BaseComponent { | ||
render() { | ||
let { props } = this; | ||
let { tDateProfile, cellElRefs } = props; | ||
let { slotDates, isWeekStarts } = tDateProfile; | ||
let isDay = !tDateProfile.isTimeScale && !tDateProfile.largeUnit; | ||
return (createElement("tbody", null, | ||
createElement("tr", null, slotDates.map((slotDate, i) => { | ||
let key = slotDate.toISOString(); | ||
return (createElement(TimelineSlatCell, { key: key, elRef: cellElRefs.createRef(key), date: slotDate, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isEm: isWeekStarts[i], isDay: isDay })); | ||
})))); | ||
function createHorizontalStyle(props, isRtl) { | ||
if (props) { | ||
return { | ||
[isRtl ? 'right' : 'left']: props.start, | ||
width: props.size, | ||
}; | ||
} | ||
} | ||
class TimelineSlats extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
this.rootElRef = createRef(); | ||
this.cellElRefs = new RefMap(); | ||
this.handleScrollRequest = (request) => { | ||
let { onScrollLeftRequest } = this.props; | ||
let { coords } = this; | ||
if (onScrollLeftRequest && coords) { | ||
if (request.time) { | ||
let scrollLeft = coords.coordFromLeft(coords.durationToCoord(request.time)); | ||
onScrollLeftRequest(scrollLeft); | ||
} | ||
return true; | ||
} | ||
return null; // best? | ||
}; | ||
// Timeline-specific | ||
// ------------------------------------------------------------------------------------------------- | ||
const MIN_SLOT_WIDTH = 30; // for real | ||
/* | ||
TODO: DRY with computeSlatHeight? | ||
*/ | ||
function computeSlotWidth(slatCnt, slatsPerLabel, slatMinWidth, labelInnerWidth, viewportWidth) { | ||
if (labelInnerWidth == null || viewportWidth == null) { | ||
return [undefined, undefined, false]; | ||
} | ||
render() { | ||
let { props, context } = this; | ||
return (createElement("div", { className: "fc-timeline-slots", ref: this.rootElRef }, | ||
createElement("table", { "aria-hidden": true, className: context.theme.getClass('table'), style: { | ||
minWidth: props.tableMinWidth, | ||
width: props.clientWidth, | ||
} }, | ||
props.tableColGroupNode, | ||
createElement(TimelineSlatsBody, { cellElRefs: this.cellElRefs, dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange })))); | ||
slatMinWidth = Math.max(slatMinWidth || 0, (labelInnerWidth + 1) / slatsPerLabel, MIN_SLOT_WIDTH); | ||
const slatTryWidth = viewportWidth / slatCnt; | ||
let slatLiquid; | ||
let slatWidth; | ||
if (slatTryWidth >= slatMinWidth) { | ||
slatLiquid = true; | ||
slatWidth = slatTryWidth; | ||
} | ||
componentDidMount() { | ||
this.updateSizing(); | ||
this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest); | ||
else { | ||
slatLiquid = false; | ||
slatWidth = Math.max(slatMinWidth, slatTryWidth); | ||
} | ||
componentDidUpdate(prevProps) { | ||
this.updateSizing(); | ||
this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile); | ||
return [slatWidth * slatCnt, slatWidth, slatLiquid]; | ||
} | ||
function timeToCoord(// pixels | ||
time, dateEnv, dateProfile, tDateProfile, slowWidth) { | ||
let date = dateEnv.add(dateProfile.activeRange.start, time); | ||
if (!tDateProfile.isTimeScale) { | ||
date = startOfDay(date); | ||
} | ||
componentWillUnmount() { | ||
this.scrollResponder.detach(); | ||
if (this.props.onCoords) { | ||
this.props.onCoords(null); | ||
} | ||
return dateToCoord(date, dateEnv, tDateProfile, slowWidth); | ||
} | ||
function dateToCoord(// pixels | ||
date, dateEnv, tDateProfile, slotWidth) { | ||
let snapCoverage = computeDateSnapCoverage(date, tDateProfile, dateEnv); | ||
let slotCoverage = snapCoverage / tDateProfile.snapsPerSlot; | ||
return slotCoverage * slotWidth; | ||
} | ||
/* | ||
returned value is between 0 and the number of snaps | ||
*/ | ||
function computeDateSnapCoverage(date, tDateProfile, dateEnv) { | ||
let snapDiff = dateEnv.countDurationsBetween(tDateProfile.normalizedRange.start, date, tDateProfile.snapDuration); | ||
if (snapDiff < 0) { | ||
return 0; | ||
} | ||
updateSizing() { | ||
let { props, context } = this; | ||
if (props.clientWidth !== null && // is sizing stable? | ||
this.scrollResponder | ||
// ^it's possible to have clientWidth immediately after mount (when returning from print view), but w/o scrollResponder | ||
) { | ||
let rootEl = this.rootElRef.current; | ||
if (rootEl.offsetWidth) { // not hidden by css | ||
this.coords = new TimelineCoords(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.tDateProfile.slotDates), props.dateProfile, props.tDateProfile, context.dateEnv, context.isRtl); | ||
if (props.onCoords) { | ||
props.onCoords(this.coords); | ||
} | ||
this.scrollResponder.update(false); // TODO: wouldn't have to do this if coords were in state | ||
} | ||
} | ||
if (snapDiff >= tDateProfile.snapDiffToIndex.length) { | ||
return tDateProfile.snapCnt; | ||
} | ||
positionToHit(leftPosition) { | ||
let { outerCoordCache } = this.coords; | ||
let { dateEnv, isRtl } = this.context; | ||
let { tDateProfile } = this.props; | ||
let slatIndex = outerCoordCache.leftToIndex(leftPosition); | ||
if (slatIndex != null) { | ||
// somewhat similar to what TimeGrid does. consolidate? | ||
let slatWidth = outerCoordCache.getWidth(slatIndex); | ||
let partial = isRtl ? | ||
(outerCoordCache.rights[slatIndex] - leftPosition) / slatWidth : | ||
(leftPosition - outerCoordCache.lefts[slatIndex]) / slatWidth; | ||
let localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot); | ||
let start = dateEnv.add(tDateProfile.slotDates[slatIndex], multiplyDuration(tDateProfile.snapDuration, localSnapIndex)); | ||
let end = dateEnv.add(start, tDateProfile.snapDuration); | ||
return { | ||
dateSpan: { | ||
range: { start, end }, | ||
allDay: !this.props.tDateProfile.isTimeScale, | ||
}, | ||
dayEl: this.cellElRefs.currentMap[slatIndex], | ||
left: outerCoordCache.lefts[slatIndex], | ||
right: outerCoordCache.rights[slatIndex], | ||
}; | ||
} | ||
return null; | ||
let snapDiffInt = Math.floor(snapDiff); | ||
let snapCoverage = tDateProfile.snapDiffToIndex[snapDiffInt]; | ||
if (isInt(snapCoverage)) { // not an in-between value | ||
snapCoverage += snapDiff - snapDiffInt; // add the remainder | ||
} | ||
else { | ||
// a fractional value, meaning the date is not visible | ||
// always round up in this case. works for start AND end dates in a range. | ||
snapCoverage = Math.ceil(snapCoverage); | ||
} | ||
return snapCoverage; | ||
} | ||
function collectCellEls(elMap, slotDates) { | ||
return slotDates.map((slotDate) => { | ||
let key = slotDate.toISOString(); | ||
return elMap[key]; | ||
}); | ||
} | ||
function computeSegHCoords(segs, minWidth, timelineCoords) { | ||
let hcoords = []; | ||
if (timelineCoords) { | ||
for (let seg of segs) { | ||
let res = timelineCoords.rangeToCoords(seg); | ||
let start = Math.round(res.start); // for barely-overlapping collisions | ||
let end = Math.round(res.end); // | ||
if (end - start < minWidth) { | ||
end = start + minWidth; | ||
} | ||
hcoords.push({ start, end }); | ||
} | ||
function computeManySegHorizontals(segs, segMinWidth, dateEnv, tDateProfile, slotWidth) { | ||
const res = {}; | ||
for (const seg of segs) { | ||
res[seg.eventRange.instance.instanceId] = computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth); | ||
} | ||
return hcoords; | ||
return res; | ||
} | ||
function computeFgSegPlacements(segs, segHCoords, // might not have for every seg | ||
eventInstanceHeights, // might not have for every seg | ||
moreLinkHeights, // might not have for every more-link | ||
function computeSegHorizontals(seg, segMinWidth, dateEnv, tDateProfile, slotWidth) { | ||
const startCoord = dateToCoord(seg.start, dateEnv, tDateProfile, slotWidth); | ||
const endCoord = dateToCoord(seg.end, dateEnv, tDateProfile, slotWidth); | ||
let size = endCoord - startCoord; | ||
if (segMinWidth) { | ||
size = Math.max(size, segMinWidth); | ||
} | ||
return { start: startCoord, size }; | ||
} | ||
function computeFgSegPlacements(// mostly horizontals | ||
segs, segHorizontals, segHeights, // keyed by instanceId | ||
strictOrder, maxStackCnt) { | ||
let segInputs = []; | ||
let crudePlacements = []; // when we don't know dims | ||
let segEntries = []; | ||
for (let i = 0; i < segs.length; i += 1) { | ||
let seg = segs[i]; | ||
let instanceId = seg.eventRange.instance.instanceId; | ||
let height = eventInstanceHeights[instanceId]; | ||
let hcoords = segHCoords[i]; | ||
if (height && hcoords) { | ||
segInputs.push({ | ||
let height = segHeights.get(instanceId); | ||
let hcoords = segHorizontals[instanceId]; | ||
if (height != null && hcoords != null) { | ||
segEntries.push({ | ||
index: i, | ||
span: hcoords, | ||
seg, | ||
span: { | ||
start: hcoords.start, | ||
end: hcoords.start + hcoords.size, | ||
}, | ||
thickness: height, | ||
}); | ||
} | ||
else { | ||
crudePlacements.push({ | ||
seg, | ||
hcoords, | ||
top: null, | ||
}); | ||
} | ||
} | ||
@@ -851,54 +722,58 @@ let hierarchy = new SegHierarchy(); | ||
} | ||
let hiddenEntries = hierarchy.addSegs(segInputs); | ||
let hiddenPlacements = hiddenEntries.map((entry) => ({ | ||
seg: segs[entry.index], | ||
hcoords: entry.span, | ||
top: null, | ||
let hiddenEntries = hierarchy.addSegs(segEntries); | ||
let hiddenGroups = groupIntersectingEntries(hiddenEntries); | ||
let hiddenGroupEntries = hiddenGroups.map((hiddenGroup, index) => ({ | ||
index: segs.length + index, | ||
segGroup: hiddenGroup, | ||
span: hiddenGroup.span, | ||
thickness: 1, // HACK to ensure it's placed | ||
})); | ||
let hiddenGroups = groupIntersectingEntries(hiddenEntries); | ||
let moreLinkInputs = []; | ||
let moreLinkCrudePlacements = []; | ||
const extractSeg = (entry) => segs[entry.index]; | ||
for (let i = 0; i < hiddenGroups.length; i += 1) { | ||
let hiddenGroup = hiddenGroups[i]; | ||
let sortedSegs = hiddenGroup.entries.map(extractSeg); | ||
let height = moreLinkHeights[buildIsoString(computeEarliestSegStart(sortedSegs))]; // not optimal :( | ||
if (height != null) { | ||
// NOTE: the hiddenGroup's spanStart/spanEnd are already computed by rangeToCoords. computed during input. | ||
moreLinkInputs.push({ | ||
index: segs.length + i, | ||
thickness: height, | ||
span: hiddenGroup.span, | ||
}); | ||
} | ||
else { | ||
moreLinkCrudePlacements.push({ | ||
seg: sortedSegs, | ||
hcoords: hiddenGroup.span, | ||
top: null, | ||
}); | ||
} | ||
} | ||
// add more-links into the hierarchy, but don't limit | ||
hierarchy.maxStackCnt = -1; | ||
hierarchy.addSegs(moreLinkInputs); | ||
hierarchy.addSegs(hiddenGroupEntries); | ||
let visibleRects = hierarchy.toRects(); | ||
let visiblePlacements = []; | ||
let maxHeight = 0; | ||
let segTops = {}; | ||
let hiddenGroupTops = {}; | ||
for (let rect of visibleRects) { | ||
let segIndex = rect.index; | ||
visiblePlacements.push({ | ||
seg: segIndex < segs.length | ||
? segs[segIndex] // a real seg | ||
: hiddenGroups[segIndex - segs.length].entries.map(extractSeg), | ||
hcoords: rect.span, | ||
top: rect.levelCoord, | ||
}); | ||
maxHeight = Math.max(maxHeight, rect.levelCoord + rect.thickness); | ||
const { seg, segGroup } = rect; | ||
if (seg) { // regular seg | ||
segTops[seg.eventRange.instance.instanceId] = rect.levelCoord; | ||
} | ||
else { // hiddenGroup | ||
hiddenGroupTops[segGroup.key] = rect.levelCoord; | ||
} | ||
} | ||
return [ | ||
visiblePlacements.concat(crudePlacements, hiddenPlacements, moreLinkCrudePlacements), | ||
maxHeight, | ||
segTops, | ||
computeMaxBottom(segs, segTops, segHeights), | ||
hiddenGroups, | ||
hiddenGroupTops, | ||
]; | ||
} | ||
function computeMaxBottom(segs, segTops, segHeights) { | ||
let max = 0; | ||
for (const seg of segs) { | ||
const { instanceId } = seg.eventRange.instance; | ||
const top = segTops[instanceId]; | ||
const height = segHeights.get(instanceId); | ||
if (top != null && height != null) { | ||
max = Math.max(max, top + height); | ||
} | ||
} | ||
return max; | ||
} | ||
/* | ||
TODO: converge with computeMaxBottom, but keys are different | ||
*/ | ||
function computeMoreLinkMaxBottom(hiddenGroups, hiddenGroupTops, hiddenGroupHeights) { | ||
let max = 0; | ||
for (const hiddenGroup of hiddenGroups) { | ||
const top = hiddenGroupTops[hiddenGroup.key]; | ||
const height = hiddenGroupHeights.get(hiddenGroup.key); | ||
if (top != null && height != null) { | ||
max = Math.max(max, top + height); | ||
} | ||
} | ||
return max; | ||
} | ||
@@ -909,19 +784,20 @@ class TimelineLaneBg extends BaseComponent { | ||
let highlightSeg = [].concat(props.eventResizeSegs, props.dateSelectionSegs); | ||
return props.timelineCoords && (createElement("div", { className: "fc-timeline-bg" }, | ||
this.renderSegs(props.businessHourSegs || [], props.timelineCoords, 'non-business'), | ||
this.renderSegs(props.bgEventSegs || [], props.timelineCoords, 'bg-event'), | ||
this.renderSegs(highlightSeg, props.timelineCoords, 'highlight'))); | ||
return (createElement("div", { className: "fc-timeline-bg" }, | ||
this.renderSegs(props.businessHourSegs || [], 'non-business'), | ||
this.renderSegs(props.bgEventSegs || [], 'bg-event'), | ||
this.renderSegs(highlightSeg, 'highlight'))); | ||
} | ||
renderSegs(segs, timelineCoords, fillType) { | ||
let { todayRange, nowDate } = this.props; | ||
let { isRtl } = this.context; | ||
let segHCoords = computeSegHCoords(segs, 0, timelineCoords); | ||
let children = segs.map((seg, i) => { | ||
let hcoords = segHCoords[i]; | ||
let hStyle = coordsToCss(hcoords, isRtl); | ||
renderSegs(segs, fillType) { | ||
let { tDateProfile, todayRange, nowDate, slotWidth } = this.props; | ||
let { dateEnv, isRtl } = this.context; | ||
return (createElement(Fragment, null, segs.map((seg) => { | ||
let hStyle; // TODO | ||
if (slotWidth != null) { | ||
let segHorizontal = computeSegHorizontals(seg, undefined, dateEnv, tDateProfile, slotWidth); | ||
hStyle = horizontalsToCss(segHorizontal, isRtl); | ||
} | ||
return (createElement("div", { key: buildEventRangeKey(seg.eventRange), className: "fc-timeline-bg-harness", style: hStyle }, fillType === 'bg-event' ? | ||
createElement(BgEvent, Object.assign({ seg: seg }, getSegMeta(seg, todayRange, nowDate))) : | ||
renderFill(fillType))); | ||
}); | ||
return createElement(Fragment, null, children); | ||
}))); | ||
} | ||
@@ -935,4 +811,4 @@ } | ||
// protect against when the span is entirely in an invalid date region | ||
if (computeDateSnapCoverage(normalRange.start, tDateProfile, dateEnv) | ||
< computeDateSnapCoverage(normalRange.end, tDateProfile, dateEnv)) { | ||
if (computeDateSnapCoverage$1(normalRange.start, tDateProfile, dateEnv) | ||
< computeDateSnapCoverage$1(normalRange.end, tDateProfile, dateEnv)) { | ||
// intersect the footprint's range with the grid's range | ||
@@ -963,4 +839,11 @@ let slicedRange = intersectRanges(normalRange, tDateProfile.normalizedRange); | ||
render() { | ||
let { props } = this; | ||
return (createElement(StandardEvent, Object.assign({}, props, { elClasses: ['fc-timeline-event', 'fc-h-event'], defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale }))); | ||
let { props, context } = this; | ||
let { options } = context; | ||
return (createElement(StandardEvent, Object.assign({}, props, { elClasses: [ | ||
'fc-timeline-event', | ||
'fc-h-event', | ||
options.eventOverlap === false // TODO: fix bad default | ||
? 'fc-timeline-event-spacious' | ||
: '' | ||
], defaultTimeFormat: DEFAULT_TIME_FORMAT, defaultDisplayEventTime: !props.isTimeScale }))); | ||
} | ||
@@ -971,37 +854,66 @@ } | ||
render() { | ||
let { props, context } = this; | ||
let { hiddenSegs, placement, resourceId } = props; | ||
let { top, hcoords } = placement; | ||
let isVisible = hcoords && top !== null; | ||
let hStyle = coordsToCss(hcoords, context.isRtl); | ||
let { props } = this; | ||
let { hiddenSegs, resourceId, forcedInvisibleMap } = props; | ||
let extraDateSpan = resourceId ? { resourceId } : {}; | ||
return (createElement(MoreLinkContainer, { elRef: props.elRef, elClasses: ['fc-timeline-more-link'], elStyle: Object.assign({ visibility: isVisible ? '' : 'hidden', top: top || 0 }, hStyle), allDayDate: null, moreCnt: hiddenSegs.length, allSegs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: extraDateSpan, popoverContent: () => (createElement(Fragment, null, hiddenSegs.map((seg) => { | ||
return (createElement(MoreLinkContainer, { elClasses: ['fc-timeline-more-link'], allDayDate: null, segs: hiddenSegs, hiddenSegs: hiddenSegs, dateProfile: props.dateProfile, todayRange: props.todayRange, extraDateSpan: extraDateSpan, popoverContent: () => (createElement(Fragment, null, hiddenSegs.map((seg) => { | ||
let instanceId = seg.eventRange.instance.instanceId; | ||
return (createElement("div", { key: instanceId, style: { visibility: props.isForcedInvisible[instanceId] ? 'hidden' : '' } }, | ||
return (createElement("div", { key: instanceId, style: { visibility: forcedInvisibleMap[instanceId] ? 'hidden' : '' } }, | ||
createElement(TimelineEvent, Object.assign({ isTimeScale: props.isTimeScale, seg: seg, isDragging: false, isResizing: false, isDateSelecting: false, isSelected: instanceId === props.eventSelection }, getSegMeta(seg, props.todayRange, props.nowDate))))); | ||
}))) }, (InnerContent) => (createElement(InnerContent, { elTag: "div", elClasses: ['fc-timeline-more-link-inner', 'fc-sticky'] })))); | ||
}))) }, (InnerContent) => (createElement(InnerContent, { elTag: "div", elClasses: ['fc-timeline-more-link-inner', 'fc-sticky-x'] })))); | ||
} | ||
} | ||
/* | ||
TODO: make DRY with other Event Harnesses | ||
*/ | ||
class TimelineEventHarness extends Component { | ||
constructor() { | ||
super(...arguments); | ||
// ref | ||
this.rootElRef = createRef(); | ||
} | ||
render() { | ||
const { props } = this; | ||
return (createElement("div", { className: "fc-abs", style: props.style, ref: this.rootElRef }, props.children)); | ||
} | ||
componentDidMount() { | ||
const rootEl = this.rootElRef.current; // TODO: make dynamic with useEffect | ||
this.detachHeight = watchHeight(rootEl, (height) => { | ||
setRef(this.props.heightRef, height); | ||
}); | ||
} | ||
componentWillUnmount() { | ||
this.detachHeight(); | ||
} | ||
} | ||
/* | ||
TODO: split TimelineLaneBg and TimelineLaneFg? | ||
*/ | ||
class TimelineLane extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
// memo | ||
this.sortEventSegs = memoize(sortEventSegs); | ||
// refs | ||
this.segHeightRefMap = new RefMap(() => { | ||
afterSize(this.handleSegHeights); | ||
}); | ||
this.moreLinkHeightRefMap = new RefMap(() => { | ||
afterSize(this.handleMoreLinkHeights); | ||
}); | ||
// internal | ||
this.slicer = new TimelineLaneSlicer(); | ||
this.sortEventSegs = memoize(sortEventSegs); | ||
this.harnessElRefs = new RefMap(); | ||
this.moreElRefs = new RefMap(); | ||
this.innerElRef = createRef(); | ||
// TODO: memoize event positioning | ||
this.state = { | ||
eventInstanceHeights: {}, | ||
moreLinkHeights: {}, | ||
this.handleMoreLinkHeights = () => { | ||
this.setState({ moreLinkHeightRev: this.moreLinkHeightRefMap.rev }); // will trigger rerender | ||
}; | ||
this.handleResize = (isForced) => { | ||
if (isForced) { | ||
this.updateSize(); | ||
} | ||
this.handleSegHeights = () => { | ||
this.setState({ segHeightRev: this.segHeightRefMap.rev }); // will trigger rerender | ||
}; | ||
} | ||
/* | ||
TODO: lots of memoization needed here! | ||
*/ | ||
render() { | ||
let { props, state, context } = this; | ||
let { props, context, segHeightRefMap } = this; | ||
let { options } = context; | ||
@@ -1015,5 +927,10 @@ let { dateProfile, tDateProfile } = props; | ||
let fgSegs = this.sortEventSegs(slicedProps.fgEventSegs, options.eventOrder); | ||
let fgSegHCoords = computeSegHCoords(fgSegs, options.eventMinWidth, props.timelineCoords); | ||
let [fgPlacements, fgHeight] = computeFgSegPlacements(fgSegs, fgSegHCoords, state.eventInstanceHeights, state.moreLinkHeights, options.eventOrderStrict, options.eventMaxStack); | ||
let isForcedInvisible = // TODO: more convenient | ||
let fgSegHorizontals = props.slotWidth != null | ||
? computeManySegHorizontals(fgSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth) | ||
: {}; | ||
let [fgSegTops, fgSegsBottom, hiddenGroups, hiddenGroupTops] = computeFgSegPlacements(// verticals | ||
fgSegs, fgSegHorizontals, segHeightRefMap.current, options.eventOrderStrict, options.eventMaxStack); | ||
let moreLinksBottom = computeMoreLinkMaxBottom(hiddenGroups, hiddenGroupTops, this.moreLinkHeightRefMap.current); | ||
let innerHeight = Math.max(moreLinksBottom, fgSegsBottom); | ||
let forcedInvisibleMap = // TODO: more convenient/DRY | ||
(slicedProps.eventDrag ? slicedProps.eventDrag.affectedInstances : null) || | ||
@@ -1023,95 +940,259 @@ (slicedProps.eventResize ? slicedProps.eventResize.affectedInstances : null) || | ||
return (createElement(Fragment, null, | ||
createElement(TimelineLaneBg, { businessHourSegs: slicedProps.businessHourSegs, bgEventSegs: slicedProps.bgEventSegs, timelineCoords: props.timelineCoords, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : [] /* bad new empty array? */, dateSelectionSegs: slicedProps.dateSelectionSegs, nowDate: props.nowDate, todayRange: props.todayRange }), | ||
createElement("div", { className: "fc-timeline-events fc-scrollgrid-sync-inner", ref: this.innerElRef, style: { height: fgHeight } }, | ||
this.renderFgSegs(fgPlacements, isForcedInvisible, false, false, false), | ||
this.renderFgSegs(buildMirrorPlacements(mirrorSegs, props.timelineCoords, fgPlacements), {}, Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false)))); | ||
createElement(TimelineLaneBg, { tDateProfile: tDateProfile, nowDate: props.nowDate, todayRange: props.todayRange, | ||
// content | ||
bgEventSegs: slicedProps.bgEventSegs, businessHourSegs: slicedProps.businessHourSegs, dateSelectionSegs: slicedProps.dateSelectionSegs, eventResizeSegs: slicedProps.eventResize ? slicedProps.eventResize.segs : [] /* bad new empty array? */, | ||
// dimensions | ||
slotWidth: props.slotWidth }), | ||
createElement("div", { className: [ | ||
'fc-timeline-events', | ||
'fc-content-box', | ||
options.eventOverlap === false // TODO: fix bad default | ||
? 'fc-timeline-events-overlap-disabled' | ||
: 'fc-timeline-events-overlap-enabled' | ||
].join(' '), style: { height: innerHeight } }, | ||
this.renderFgSegs(fgSegs, fgSegHorizontals, fgSegTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, false, // isDragging | ||
false, // isResizing | ||
false), | ||
this.renderFgSegs(mirrorSegs, props.slotWidth // TODO: memoize | ||
? computeManySegHorizontals(mirrorSegs, options.eventMinWidth, context.dateEnv, tDateProfile, props.slotWidth) | ||
: {}, fgSegTops, {}, // forcedInvisibleMap | ||
[], {}, Boolean(slicedProps.eventDrag), Boolean(slicedProps.eventResize), false)))); | ||
} | ||
renderFgSegs(segs, segHorizontals, segTops, forcedInvisibleMap, hiddenGroups, hiddenGroupTops, isDragging, isResizing, isDateSelecting) { | ||
let { props, context, segHeightRefMap, moreLinkHeightRefMap } = this; | ||
let isMirror = isDragging || isResizing || isDateSelecting; | ||
return (createElement(Fragment, null, | ||
segs.map((seg) => { | ||
const { instanceId } = seg.eventRange.instance; | ||
const segTop = segTops[instanceId]; | ||
const segHorizontal = segHorizontals[instanceId]; | ||
const isVisible = isMirror || | ||
(segHorizontal && segTop != null && !forcedInvisibleMap[instanceId]); | ||
return (createElement(TimelineEventHarness, { key: instanceId, style: Object.assign({ visibility: isVisible ? '' : 'hidden', top: segTop || 0 }, horizontalsToCss(segHorizontal, context.isRtl)), heightRef: isMirror ? undefined : segHeightRefMap.createRef(instanceId) }, | ||
createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection /* TODO: bad for mirror? */ }, getSegMeta(seg, props.todayRange, props.nowDate))))); | ||
}), | ||
hiddenGroups.map((hiddenGroup) => (createElement(TimelineEventHarness, { key: hiddenGroup.key, style: Object.assign({ top: hiddenGroupTops[hiddenGroup.key] || 0 }, horizontalsToCss({ | ||
start: hiddenGroup.span.start, | ||
size: hiddenGroup.span.end - hiddenGroup.span.start | ||
}, context.isRtl)), heightRef: moreLinkHeightRefMap.createRef(hiddenGroup.key) }, | ||
createElement(TimelineLaneMoreLink, { hiddenSegs: hiddenGroup.segs /* TODO: make SegGroup generic! */, dateProfile: props.dateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isTimeScale: props.tDateProfile.isTimeScale, eventSelection: props.eventSelection, resourceId: props.resourceId, forcedInvisibleMap: forcedInvisibleMap })))))); | ||
} | ||
} | ||
class TimelineHeaderCell extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
// memo | ||
this.refineRenderProps = memoizeObjArg(refineRenderProps); | ||
this.buildCellNavLinkAttrs = memoize(buildCellNavLinkAttrs); | ||
// ref | ||
this.innerElRef = createRef(); | ||
// TODO: unset width/height ref on unmount? | ||
} | ||
render() { | ||
let { props, context } = this; | ||
let { dateEnv, options } = context; | ||
let { cell, dateProfile, tDateProfile } = props; | ||
// the cell.rowUnit is f'd | ||
// giving 'month' for a 3-day view | ||
// workaround: to infer day, do NOT time | ||
let dateMeta = getDateMeta(cell.date, props.todayRange, props.nowDate, dateProfile); | ||
let renderProps = this.refineRenderProps({ | ||
level: props.rowLevel, | ||
dateMarker: cell.date, | ||
text: cell.text, | ||
dateEnv: context.dateEnv, | ||
viewApi: context.viewApi, | ||
}); | ||
return (createElement(ContentContainer, { elTag: "div", elClasses: [ | ||
'fc-timeline-slot-label', | ||
'fc-timeline-slot', | ||
cell.isWeekStart ? 'fc-timeline-slot-em' : '', | ||
'fc-header-cell', | ||
'fc-cell', | ||
'fc-flex-column', | ||
'fc-justify-center', | ||
props.isCentered ? 'fc-align-center' : 'fc-align-start', | ||
...( // TODO: so slot classnames for week/month/bigger. see note above about rowUnit | ||
cell.rowUnit === 'time' ? | ||
getSlotClassNames(dateMeta, context.theme) : | ||
getDayClassNames(dateMeta, context.theme)), | ||
], elAttrs: { | ||
'data-date': dateEnv.formatIso(cell.date, { | ||
omitTime: !tDateProfile.isTimeScale, | ||
omitTimeZoneOffset: true, | ||
}), | ||
}, elStyle: { | ||
width: props.slotWidth != null | ||
? props.slotWidth * cell.colspan | ||
: undefined, | ||
}, renderProps: renderProps, generatorName: "slotLabelContent", customGenerator: options.slotLabelContent, defaultGenerator: renderInnerContent, classNameGenerator: options.slotLabelClassNames, didMount: options.slotLabelDidMount, willUnmount: options.slotLabelWillUnmount }, (InnerContent) => (createElement("div", { ref: this.innerElRef, className: [ | ||
'fc-flex-column', | ||
props.isSticky ? 'fc-sticky-x' : '', | ||
].join(' ') }, | ||
createElement(InnerContent, { elTag: "a", elClasses: [ | ||
'fc-cell-inner', | ||
'fc-padding-md', | ||
], elAttrs: this.buildCellNavLinkAttrs(context, cell.date, cell.rowUnit) }))))); | ||
} | ||
componentDidMount() { | ||
this.updateSize(); | ||
this.context.addResizeHandler(this.handleResize); | ||
const { props } = this; | ||
const innerEl = this.innerElRef.current; // TODO: make dynamic with useEffect | ||
this.detachSize = watchSize(innerEl, (width, height) => { | ||
setRef(props.innerWidthRef, width); | ||
setRef(props.innerHeightRef, height); | ||
// HACK for sticky-centering | ||
innerEl.style.left = innerEl.style.right = | ||
(props.isCentered && props.isSticky) | ||
? `calc(50% - ${width / 2}px)` | ||
: ''; | ||
}); | ||
} | ||
componentDidUpdate(prevProps, prevState) { | ||
if (prevProps.eventStore !== this.props.eventStore || // external thing changed? | ||
prevProps.timelineCoords !== this.props.timelineCoords || // external thing changed? | ||
prevState.moreLinkHeights !== this.state.moreLinkHeights // HACK. see addStateEquality | ||
) { | ||
this.updateSize(); | ||
} | ||
} | ||
componentWillUnmount() { | ||
this.context.removeResizeHandler(this.handleResize); | ||
this.detachSize(); | ||
} | ||
updateSize() { | ||
let { props } = this; | ||
let { timelineCoords } = props; | ||
const innerEl = this.innerElRef.current; | ||
if (props.onHeightChange) { | ||
props.onHeightChange(innerEl, false); | ||
} | ||
if (timelineCoords) { | ||
this.setState({ | ||
eventInstanceHeights: mapHash(this.harnessElRefs.currentMap, (harnessEl) => (Math.round(harnessEl.getBoundingClientRect().height))), | ||
moreLinkHeights: mapHash(this.moreElRefs.currentMap, (moreEl) => (Math.round(moreEl.getBoundingClientRect().height))), | ||
}, () => { | ||
if (props.onHeightChange) { | ||
props.onHeightChange(innerEl, true); | ||
} | ||
}); | ||
} | ||
// hack | ||
if (props.syncParentMinHeight) { | ||
innerEl.parentElement.style.minHeight = innerEl.style.height; | ||
} | ||
} | ||
// Utils | ||
// ------------------------------------------------------------------------------------------------- | ||
function buildCellNavLinkAttrs(context, cellDate, rowUnit) { | ||
return (rowUnit && rowUnit !== 'time') | ||
? buildNavLinkAttrs(context, cellDate, rowUnit) | ||
: {}; | ||
} | ||
function renderInnerContent(renderProps) { | ||
return renderProps.text; | ||
} | ||
function refineRenderProps(input) { | ||
return { | ||
level: input.level, | ||
date: input.dateEnv.toDate(input.dateMarker), | ||
view: input.viewApi, | ||
text: input.text, | ||
}; | ||
} | ||
class TimelineHeaderRow extends BaseComponent { | ||
constructor() { | ||
super(...arguments); | ||
// refs | ||
this.innerWidthRefMap = new RefMap(() => { | ||
afterSize(this.handleInnerWidths); | ||
}); | ||
this.innerHeightRefMap = new RefMap(() => { | ||
afterSize(this.handleInnerHeights); | ||
}); | ||
this.handleInnerWidths = () => { | ||
const innerWidthMap = this.innerWidthRefMap.current; | ||
let max = 0; | ||
for (const innerWidth of innerWidthMap.values()) { | ||
max = Math.max(max, innerWidth); | ||
} | ||
// TODO: ensure not equal? | ||
setRef(this.props.innerWidthRef, max); | ||
}; | ||
this.handleInnerHeights = () => { | ||
const innerHeightMap = this.innerHeightRefMap.current; | ||
let max = 0; | ||
for (const innerHeight of innerHeightMap.values()) { | ||
max = Math.max(max, innerHeight); | ||
} | ||
// TODO: ensure not equal? | ||
setRef(this.props.innerHeighRef, max); | ||
}; | ||
} | ||
renderFgSegs(segPlacements, isForcedInvisible, isDragging, isResizing, isDateSelecting) { | ||
let { harnessElRefs, moreElRefs, props, context } = this; | ||
let isMirror = isDragging || isResizing || isDateSelecting; | ||
return (createElement(Fragment, null, segPlacements.map((segPlacement) => { | ||
let { seg, hcoords, top } = segPlacement; | ||
if (Array.isArray(seg)) { // a more-link | ||
let isoStr = buildIsoString(computeEarliestSegStart(seg)); | ||
return (createElement(TimelineLaneMoreLink, { key: 'm:' + isoStr /* "m" for "more" */, elRef: moreElRefs.createRef(isoStr), hiddenSegs: seg, placement: segPlacement, dateProfile: props.dateProfile, nowDate: props.nowDate, todayRange: props.todayRange, isTimeScale: props.tDateProfile.isTimeScale, eventSelection: props.eventSelection, resourceId: props.resourceId, isForcedInvisible: isForcedInvisible })); | ||
} | ||
let instanceId = seg.eventRange.instance.instanceId; | ||
let isVisible = isMirror || Boolean(!isForcedInvisible[instanceId] && hcoords && top !== null); | ||
let hStyle = coordsToCss(hcoords, context.isRtl); | ||
return (createElement("div", { key: 'e:' + instanceId /* "e" for "event" */, ref: isMirror ? null : harnessElRefs.createRef(instanceId), className: "fc-timeline-event-harness", style: Object.assign({ visibility: isVisible ? '' : 'hidden', top: top || 0 }, hStyle) }, | ||
createElement(TimelineEvent, Object.assign({ isTimeScale: props.tDateProfile.isTimeScale, seg: seg, isDragging: isDragging, isResizing: isResizing, isDateSelecting: isDateSelecting, isSelected: instanceId === props.eventSelection /* TODO: bad for mirror? */ }, getSegMeta(seg, props.todayRange, props.nowDate))))); | ||
render() { | ||
const { props, innerWidthRefMap, innerHeightRefMap } = this; | ||
const isCentered = !(props.tDateProfile.isTimeScale && props.isLastRow); | ||
const isSticky = !props.isLastRow; | ||
return (createElement("div", { className: 'fc-row', style: { height: props.height } }, props.cells.map((cell) => { | ||
// TODO: make this part of the cell obj? | ||
// TODO: rowUnit seems wrong sometimes. says 'month' when it should be day | ||
// TODO: rowUnit is relevant to whole row. put it on a row object, not the cells | ||
const key = cell.rowUnit + ':' + cell.date.toISOString(); | ||
return (createElement(TimelineHeaderCell, { key: key, cell: cell, rowLevel: props.rowLevel, dateProfile: props.dateProfile, tDateProfile: props.tDateProfile, todayRange: props.todayRange, nowDate: props.nowDate, isCentered: isCentered, isSticky: isSticky, | ||
// refs | ||
innerWidthRef: innerWidthRefMap.createRef(key), innerHeightRef: innerHeightRefMap.createRef(key), | ||
// dimensions | ||
slotWidth: props.slotWidth })); | ||
}))); | ||
} | ||
} | ||
TimelineLane.addStateEquality({ | ||
eventInstanceHeights: isPropsEqual, | ||
moreLinkHeights: isPropsEqual, | ||
}); | ||
function buildMirrorPlacements(mirrorSegs, timelineCoords, fgPlacements) { | ||
if (!mirrorSegs.length || !timelineCoords) { | ||
return []; | ||
class TimelineNowIndicatorLine extends BaseComponent { | ||
render() { | ||
const { props, context } = this; | ||
return (createElement("div", { className: "fc-timeline-now-indicator-container" }, | ||
createElement(NowIndicatorContainer // TODO: make separate component? | ||
, { elClasses: ['fc-timeline-now-indicator-line'], elStyle: props.slotWidth != null | ||
? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl) | ||
: {}, isAxis: false, date: props.nowDate }))); | ||
} | ||
let topsByInstanceId = buildAbsoluteTopHash(fgPlacements); // TODO: cache this at first render? | ||
return mirrorSegs.map((seg) => ({ | ||
seg, | ||
hcoords: timelineCoords.rangeToCoords(seg), | ||
top: topsByInstanceId[seg.eventRange.instance.instanceId], | ||
})); | ||
} | ||
function buildAbsoluteTopHash(placements) { | ||
let topsByInstanceId = {}; | ||
for (let placement of placements) { | ||
let { seg } = placement; | ||
if (!Array.isArray(seg)) { // doesn't represent a more-link | ||
topsByInstanceId[seg.eventRange.instance.instanceId] = placement.top; | ||
} | ||
class TimelineNowIndicatorArrow extends BaseComponent { | ||
render() { | ||
const { props, context } = this; | ||
return (createElement("div", { className: "fc-timeline-now-indicator-container" }, | ||
createElement(NowIndicatorContainer, { elClasses: ['fc-timeline-now-indicator-arrow'], elStyle: props.slotWidth != null | ||
? horizontalCoordToCss(dateToCoord(props.nowDate, context.dateEnv, props.tDateProfile, props.slotWidth), context.isRtl) | ||
: {}, isAxis: true, date: props.nowDate }))); | ||
} | ||
return topsByInstanceId; | ||
} | ||
class TimelineGrid extends DateComponent { | ||
class TimelineView extends DateComponent { | ||
constructor() { | ||
super(...arguments); | ||
this.slatsRef = createRef(); | ||
this.state = { | ||
coords: null, | ||
// memoized | ||
this.buildTimelineDateProfile = memoize(buildTimelineDateProfile); | ||
this.computeSlotWidth = memoize(computeSlotWidth); | ||
// refs | ||
this.headerScrollerRef = createRef(); | ||
this.bodyScrollerRef = createRef(); | ||
this.footerScrollerRef = createRef(); | ||
// Sizing | ||
// ----------------------------------------------------------------------------------------------- | ||
this.handleHeaderSlotInnerWidth = (innerWidth) => { | ||
this.headerSlotInnerWidth = innerWidth; | ||
afterSize(this.handleSlotInnerWidths); | ||
}; | ||
this.handeEl = (el) => { | ||
this.handleBodySlotInnerWidth = (innerWidth) => { | ||
this.bodySlotInnerWidth = innerWidth; | ||
afterSize(this.handleSlotInnerWidths); | ||
}; | ||
this.handleSlotInnerWidths = () => { | ||
const { state } = this; | ||
const slotInnerWidth = Math.max(this.headerSlotInnerWidth, this.bodySlotInnerWidth); | ||
if (state.slotInnerWidth !== slotInnerWidth) { | ||
this.setState({ slotInnerWidth }); | ||
} | ||
}; | ||
this.handleScrollerWidth = (scrollerWidth) => { | ||
this.setState({ | ||
scrollerWidth, | ||
}); | ||
}; | ||
this.handleLeftScrollbarWidth = (leftScrollbarWidth) => { | ||
this.setState({ | ||
leftScrollbarWidth | ||
}); | ||
}; | ||
this.handleRightScrollbarWidth = (rightScrollbarWidth) => { | ||
this.setState({ | ||
rightScrollbarWidth | ||
}); | ||
}; | ||
this.timeScrollResponder = new ScrollResponder((time) => { | ||
const { props, context, tDateProfile, slotWidth } = this; | ||
if (slotWidth != null) { | ||
const x = timeToCoord(time, context.dateEnv, props.dateProfile, tDateProfile, slotWidth) + | ||
(context.isRtl ? -1 : 1); // overcome border. TODO: DRY this up | ||
this.syncedScroller.scrollTo({ x }); | ||
return true; | ||
} | ||
return false; | ||
}); | ||
// Hit System | ||
// ----------------------------------------------------------------------------------------------- | ||
this.handeBodyEl = (el) => { | ||
this.bodyEl = el; | ||
if (el) { | ||
@@ -1124,41 +1205,137 @@ this.context.registerInteractiveComponent(this, { el }); | ||
}; | ||
this.handleCoords = (coords) => { | ||
this.setState({ coords }); | ||
if (this.props.onSlatCoords) { | ||
this.props.onSlatCoords(coords); | ||
} | ||
}; | ||
} | ||
render() { | ||
let { props, state, context } = this; | ||
let { options } = context; | ||
let { dateProfile, tDateProfile } = props; | ||
let timerUnit = greatestDurationDenominator(tDateProfile.slotDuration).unit; | ||
return (createElement("div", { className: "fc-timeline-body", ref: this.handeEl, style: { | ||
minWidth: props.tableMinWidth, | ||
height: props.clientHeight, | ||
width: props.clientWidth, | ||
} }, | ||
createElement(NowTimer, { unit: timerUnit }, (nowDate, todayRange) => (createElement(Fragment, null, | ||
createElement(TimelineSlats, { ref: this.slatsRef, dateProfile: dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, clientWidth: props.clientWidth, tableColGroupNode: props.tableColGroupNode, tableMinWidth: props.tableMinWidth, onCoords: this.handleCoords, onScrollLeftRequest: props.onScrollLeftRequest }), | ||
createElement(TimelineLane, { dateProfile: dateProfile, tDateProfile: props.tDateProfile, nowDate: nowDate, todayRange: todayRange, nextDayThreshold: options.nextDayThreshold, businessHours: props.businessHours, eventStore: props.eventStore, eventUiBases: props.eventUiBases, dateSelection: props.dateSelection, eventSelection: props.eventSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, timelineCoords: state.coords, syncParentMinHeight: true }), | ||
(options.nowIndicator && state.coords && state.coords.isDateInRange(nowDate)) && (createElement("div", { className: "fc-timeline-now-indicator-container" }, | ||
createElement(NowIndicatorContainer, { elClasses: ['fc-timeline-now-indicator-line'], elStyle: coordToCss(state.coords.dateToCoord(nowDate), context.isRtl), isAxis: false, date: nowDate })))))))); | ||
const { props, state, context } = this; | ||
const { options } = context; | ||
/* date */ | ||
const tDateProfile = this.tDateProfile = this.buildTimelineDateProfile(props.dateProfile, context.dateEnv, options, context.dateProfileGenerator); | ||
const { cellRows } = tDateProfile; | ||
const timerUnit = greatestDurationDenominator(tDateProfile.slotDuration).unit; | ||
/* table settings */ | ||
const verticalScrolling = !props.forPrint && !getIsHeightAuto(options); | ||
const stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options); | ||
const stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(options); | ||
/* table positions */ | ||
const [canvasWidth, slotWidth] = this.computeSlotWidth(tDateProfile.slotCnt, tDateProfile.slotsPerLabel, options.slotMinWidth, state.slotInnerWidth, // is ACTUALLY the label width. rename? | ||
state.scrollerWidth); | ||
this.slotWidth = slotWidth; | ||
return (createElement(NowTimer, { unit: timerUnit }, (nowDate, todayRange) => { | ||
const enableNowIndicator = // TODO: DRY | ||
options.nowIndicator && | ||
slotWidth != null && | ||
rangeContainsMarker(props.dateProfile.currentRange, nowDate); | ||
return (createElement(ViewContainer, { viewSpec: context.viewSpec, elClasses: [ | ||
'fc-timeline-view', | ||
'fc-flex-column', | ||
'fc-border', | ||
] }, | ||
createElement(Scroller, { horizontal: true, hideScrollbars: true, elClassNames: [ | ||
'fc-timeline-header', | ||
'fc-rowgroup', | ||
stickyHeaderDates ? 'fc-sticky-header' : '', | ||
], ref: this.headerScrollerRef }, | ||
createElement("div", { className: 'fc-rel fc-content-box' // origin for now-indicator | ||
, style: { | ||
width: canvasWidth, | ||
paddingLeft: state.leftScrollbarWidth, | ||
paddingRight: state.rightScrollbarWidth, | ||
} }, | ||
createElement("div", null, cellRows.map((cells, rowLevel) => { | ||
const isLast = rowLevel === cellRows.length - 1; | ||
return (createElement(TimelineHeaderRow, { key: rowLevel, dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, rowLevel: rowLevel, isLastRow: isLast, cells: cells, slotWidth: slotWidth, innerWidthRef: isLast ? this.handleHeaderSlotInnerWidth : undefined })); | ||
})), | ||
enableNowIndicator && ( | ||
// TODO: make this positioned WITHIN padding? | ||
createElement(TimelineNowIndicatorArrow, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth })))), | ||
createElement(Scroller, { vertical: verticalScrolling, horizontal: true, elClassNames: [ | ||
'fc-timeline-body', | ||
'fc-rowgroup', | ||
verticalScrolling ? 'fc-liquid' : '', | ||
], ref: this.bodyScrollerRef, widthRef: this.handleScrollerWidth, leftScrollbarWidthRef: this.handleLeftScrollbarWidth, rightScrollbarWidthRef: this.handleRightScrollbarWidth }, | ||
createElement("div", { className: "fc-rel fc-grow", style: { | ||
width: canvasWidth, | ||
}, ref: this.handeBodyEl }, | ||
createElement(TimelineSlats, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, | ||
// ref | ||
innerWidthRef: this.handleBodySlotInnerWidth, | ||
// dimensions | ||
slotWidth: slotWidth }), | ||
createElement(TimelineLane, { dateProfile: props.dateProfile, tDateProfile: tDateProfile, nowDate: nowDate, todayRange: todayRange, nextDayThreshold: options.nextDayThreshold, eventStore: props.eventStore, eventUiBases: props.eventUiBases, businessHours: props.businessHours, dateSelection: props.dateSelection, eventDrag: props.eventDrag, eventResize: props.eventResize, eventSelection: props.eventSelection, slotWidth: slotWidth }), | ||
enableNowIndicator && (createElement(TimelineNowIndicatorLine, { tDateProfile: tDateProfile, nowDate: nowDate, slotWidth: slotWidth })))), | ||
stickyFooterScrollbar && (createElement(Scroller, { ref: this.footerScrollerRef, horizontal: true }, | ||
createElement("div", { style: { width: canvasWidth } }))))); | ||
})); | ||
} | ||
// Hit System | ||
// ------------------------------------------------------------------------------------------ | ||
// Lifecycle | ||
// ----------------------------------------------------------------------------------------------- | ||
componentDidMount() { | ||
const { context } = this; | ||
const { options } = context; | ||
const ScrollerSyncer = getScrollerSyncerClass(this.context.pluginHooks); | ||
this.syncedScroller = new ScrollerSyncer(true); // horizontal=true | ||
this.updateSyncedScroller(); | ||
context.emitter.on('_timeScrollRequest', this.timeScrollResponder.handleScroll); | ||
this.timeScrollResponder.handleScroll(options.scrollTime); | ||
} | ||
componentDidUpdate(prevProps) { | ||
const { options } = this.context; | ||
this.updateSyncedScroller(); | ||
if (prevProps.dateProfile !== this.props.dateProfile && options.scrollTimeReset) { | ||
this.timeScrollResponder.handleScroll(options.scrollTime); | ||
} | ||
else { | ||
this.timeScrollResponder.drain(); | ||
} | ||
} | ||
componentWillUnmount() { | ||
this.syncedScroller.destroy(); | ||
this.context.emitter.off('_timeScrollRequest', this.timeScrollResponder.handleScroll); | ||
} | ||
// Scrolling | ||
// ----------------------------------------------------------------------------------------------- | ||
updateSyncedScroller() { | ||
this.syncedScroller.handleChildren([ | ||
this.headerScrollerRef.current, | ||
this.bodyScrollerRef.current, | ||
this.footerScrollerRef.current | ||
], this.context.isRtl); | ||
} | ||
queryHit(positionLeft, positionTop, elWidth, elHeight) { | ||
let slats = this.slatsRef.current; | ||
let slatHit = slats.positionToHit(positionLeft); | ||
if (slatHit) { | ||
const { props, context, tDateProfile, slotWidth } = this; | ||
const { dateEnv } = context; | ||
if (slotWidth) { | ||
const x = context.isRtl ? elWidth - positionLeft : positionLeft; | ||
const slatIndex = Math.floor(x / slotWidth); | ||
const slatX = slatIndex * slotWidth; | ||
const partial = (x - slatX) / slotWidth; // floating point number between 0 and 1 | ||
const localSnapIndex = Math.floor(partial * tDateProfile.snapsPerSlot); // the snap # relative to start of slat | ||
let startDate = dateEnv.add(tDateProfile.slotDates[slatIndex], multiplyDuration(tDateProfile.snapDuration, localSnapIndex)); | ||
let endDate = dateEnv.add(startDate, tDateProfile.snapDuration); | ||
// TODO: generalize this coord stuff to TimeGrid? | ||
let snapWidth = slotWidth / tDateProfile.snapsPerSlot; | ||
let startCoord = slatIndex * slotWidth + (snapWidth * localSnapIndex); | ||
let endCoord = startCoord + snapWidth; | ||
let left, right; | ||
if (context.isRtl) { | ||
left = elWidth - endCoord; | ||
right = elWidth - startCoord; | ||
} | ||
else { | ||
left = startCoord; | ||
right = endCoord; | ||
} | ||
return { | ||
dateProfile: this.props.dateProfile, | ||
dateSpan: slatHit.dateSpan, | ||
dateProfile: props.dateProfile, | ||
dateSpan: { | ||
range: { start: startDate, end: endDate }, | ||
allDay: !tDateProfile.isTimeScale, | ||
}, | ||
rect: { | ||
left: slatHit.left, | ||
right: slatHit.right, | ||
left, | ||
right, | ||
top: 0, | ||
bottom: elHeight, | ||
}, | ||
dayEl: slatHit.dayEl, | ||
// HACK. TODO: This is expensive to do every hit-query | ||
dayEl: this.bodyEl.querySelectorAll('.fc-timeline-slot')[slatIndex], | ||
layer: 0, | ||
@@ -1171,87 +1348,2 @@ }; | ||
class TimelineView extends DateComponent { | ||
constructor() { | ||
super(...arguments); | ||
this.buildTimelineDateProfile = memoize(buildTimelineDateProfile); | ||
this.scrollGridRef = createRef(); | ||
this.state = { | ||
slatCoords: null, | ||
slotCushionMaxWidth: null, | ||
}; | ||
this.handleSlatCoords = (slatCoords) => { | ||
this.setState({ slatCoords }); | ||
}; | ||
this.handleScrollLeftRequest = (scrollLeft) => { | ||
let scrollGrid = this.scrollGridRef.current; | ||
scrollGrid.forceScrollLeft(0, scrollLeft); | ||
}; | ||
this.handleMaxCushionWidth = (slotCushionMaxWidth) => { | ||
this.setState({ | ||
slotCushionMaxWidth: Math.ceil(slotCushionMaxWidth), // for less rerendering TODO: DRY | ||
}); | ||
}; | ||
} | ||
render() { | ||
let { props, state, context } = this; | ||
let { options } = context; | ||
let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(options); | ||
let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(options); | ||
let tDateProfile = this.buildTimelineDateProfile(props.dateProfile, context.dateEnv, options, context.dateProfileGenerator); | ||
let { slotMinWidth } = options; | ||
let slatCols = buildSlatCols(tDateProfile, slotMinWidth || this.computeFallbackSlotMinWidth(tDateProfile)); | ||
let sections = [ | ||
{ | ||
type: 'header', | ||
key: 'header', | ||
isSticky: stickyHeaderDates, | ||
chunks: [{ | ||
key: 'timeline', | ||
content: (contentArg) => (createElement(TimelineHeader, { dateProfile: props.dateProfile, clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, tableMinWidth: contentArg.tableMinWidth, tableColGroupNode: contentArg.tableColGroupNode, tDateProfile: tDateProfile, slatCoords: state.slatCoords, onMaxCushionWidth: slotMinWidth ? null : this.handleMaxCushionWidth })), | ||
}], | ||
}, | ||
{ | ||
type: 'body', | ||
key: 'body', | ||
liquid: true, | ||
chunks: [{ | ||
key: 'timeline', | ||
content: (contentArg) => (createElement(TimelineGrid, Object.assign({}, props, { clientWidth: contentArg.clientWidth, clientHeight: contentArg.clientHeight, tableMinWidth: contentArg.tableMinWidth, tableColGroupNode: contentArg.tableColGroupNode, tDateProfile: tDateProfile, onSlatCoords: this.handleSlatCoords, onScrollLeftRequest: this.handleScrollLeftRequest }))), | ||
}], | ||
}, | ||
]; | ||
if (stickyFooterScrollbar) { | ||
sections.push({ | ||
type: 'footer', | ||
key: 'footer', | ||
isSticky: true, | ||
chunks: [{ | ||
key: 'timeline', | ||
content: renderScrollShim, | ||
}], | ||
}); | ||
} | ||
return (createElement(ViewContainer, { elClasses: [ | ||
'fc-timeline', | ||
options.eventOverlap === false ? | ||
'fc-timeline-overlap-disabled' : | ||
'', | ||
], viewSpec: context.viewSpec }, | ||
createElement(ScrollGrid, { ref: this.scrollGridRef, liquid: !props.isHeightAuto && !props.forPrint, forPrint: props.forPrint, collapsibleWidth: false, colGroups: [ | ||
{ cols: slatCols }, | ||
], sections: sections }))); | ||
} | ||
computeFallbackSlotMinWidth(tDateProfile) { | ||
return Math.max(30, ((this.state.slotCushionMaxWidth || 0) / tDateProfile.slotsPerLabel)); | ||
} | ||
} | ||
function buildSlatCols(tDateProfile, slotMinWidth) { | ||
return [{ | ||
span: tDateProfile.slotCnt, | ||
minWidth: slotMinWidth || 1, // needs to be a non-zero number to trigger horizontal scrollbars!?????? | ||
}]; | ||
} | ||
var css_248z = ".fc .fc-timeline-body{min-height:100%;position:relative;z-index:1}.fc .fc-timeline-slots{bottom:0;position:absolute;top:0;z-index:1}.fc .fc-timeline-slots>table{height:100%}.fc .fc-timeline-slot-minor{border-style:dotted}.fc .fc-timeline-slot-frame{align-items:center;display:flex;justify-content:center}.fc .fc-timeline-header-row-chrono .fc-timeline-slot-frame{justify-content:flex-start}.fc .fc-timeline-header-row:last-child .fc-timeline-slot-frame{overflow:hidden}.fc .fc-timeline-slot-cushion{padding:4px 5px;white-space:nowrap}.fc-direction-ltr .fc-timeline-slot{border-right:0!important}.fc-direction-rtl .fc-timeline-slot{border-left:0!important}.fc .fc-timeline-now-indicator-container{bottom:0;left:0;position:absolute;right:0;top:0;width:0;z-index:4}.fc .fc-timeline-now-indicator-arrow,.fc .fc-timeline-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;pointer-events:none;position:absolute;top:0}.fc .fc-timeline-now-indicator-arrow{border-left-color:transparent;border-right-color:transparent;border-width:6px 5px 0;margin:0 -6px}.fc .fc-timeline-now-indicator-line{border-width:0 0 0 1px;bottom:0;margin:0 -1px}.fc .fc-timeline-events{position:relative;width:0;z-index:3}.fc .fc-timeline-event-harness,.fc .fc-timeline-more-link{position:absolute;top:0}.fc-timeline-event{z-index:1}.fc-timeline-event.fc-event-mirror{z-index:2}.fc-timeline-event{align-items:center;border-radius:0;display:flex;font-size:var(--fc-small-font-size);margin-bottom:1px;padding:2px 1px;position:relative}.fc-timeline-event .fc-event-main{flex-grow:1;flex-shrink:1;min-width:0}.fc-timeline-event .fc-event-time{font-weight:700}.fc-timeline-event .fc-event-time,.fc-timeline-event .fc-event-title{padding:0 2px;white-space:nowrap}.fc-direction-ltr .fc-timeline-event.fc-event-end,.fc-direction-ltr .fc-timeline-more-link{margin-right:1px}.fc-direction-rtl .fc-timeline-event.fc-event-end,.fc-direction-rtl .fc-timeline-more-link{margin-left:1px}.fc-timeline-overlap-disabled .fc-timeline-event{margin-bottom:0;padding-bottom:5px;padding-top:5px}.fc-timeline-event:not(.fc-event-end):after,.fc-timeline-event:not(.fc-event-start):before{border-color:transparent #000;border-style:solid;border-width:5px;content:\"\";flex-grow:0;flex-shrink:0;height:0;margin:0 1px;opacity:.5;width:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-start):before,.fc-direction-rtl .fc-timeline-event:not(.fc-event-end):after{border-left:0}.fc-direction-ltr .fc-timeline-event:not(.fc-event-end):after,.fc-direction-rtl .fc-timeline-event:not(.fc-event-start):before{border-right:0}.fc-timeline-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;font-size:var(--fc-small-font-size);padding:1px}.fc-timeline-more-link-inner{display:inline-block;left:0;padding:2px;right:0}.fc .fc-timeline-bg{bottom:0;left:0;position:absolute;right:0;top:0;width:0;z-index:2}.fc .fc-timeline-bg .fc-non-business{z-index:1}.fc .fc-timeline-bg .fc-bg-event{z-index:2}.fc .fc-timeline-bg .fc-highlight{z-index:3}.fc .fc-timeline-bg-harness{bottom:0;position:absolute;top:0}"; | ||
injectStyles(css_248z); | ||
export { TimelineCoords, TimelineHeader, TimelineHeaderRows, TimelineLane, TimelineLaneBg, TimelineLaneSlicer, TimelineSlats, TimelineView, buildSlatCols, buildTimelineDateProfile, coordToCss, coordsToCss }; | ||
export { TimelineHeaderRow, TimelineLane, TimelineLaneBg, TimelineLaneSlicer, TimelineNowIndicatorArrow, TimelineNowIndicatorLine, TimelineSlats, TimelineView, buildTimelineDateProfile, computeSlotWidth, coordToCss, coordsToCss, createHorizontalStyle, createVerticalStyle, timeToCoord }; |
{ | ||
"name": "@fullcalendar/timeline", | ||
"version": "6.1.15", | ||
"version": "7.0.0-beta.0", | ||
"title": "FullCalendar Timeline Plugin", | ||
@@ -18,7 +18,7 @@ "description": "Display events on a horizontal time axis (without resources)", | ||
"dependencies": { | ||
"@fullcalendar/premium-common": "~6.1.15", | ||
"@fullcalendar/scrollgrid": "~6.1.15" | ||
"@fullcalendar/premium-common": "7.0.0-beta.0", | ||
"@fullcalendar/scrollgrid": "7.0.0-beta.0" | ||
}, | ||
"peerDependencies": { | ||
"@fullcalendar/core": "~6.1.15" | ||
"@fullcalendar/core": "7.0.0-beta.0" | ||
}, | ||
@@ -25,0 +25,0 @@ "type": "module", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
239892
4380
1
+ Added@fullcalendar/core@7.0.0-beta.0(transitive)
+ Added@fullcalendar/premium-common@7.0.0-beta.0(transitive)
+ Added@fullcalendar/scrollgrid@7.0.0-beta.0(transitive)
+ Addedpreact@10.23.2(transitive)
- Removed@fullcalendar/core@6.1.15(transitive)
- Removed@fullcalendar/premium-common@6.1.15(transitive)
- Removed@fullcalendar/scrollgrid@6.1.15(transitive)
- Removedpreact@10.12.1(transitive)