Skip to content

Commit

Permalink
make +more popover aware of its resource. fixes #5593
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Dec 18, 2020
1 parent 469ff19 commit 878e0de
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 46 deletions.
2 changes: 1 addition & 1 deletion packages-premium
15 changes: 2 additions & 13 deletions packages/common/src/component/DateComponent.ts
Expand Up @@ -94,24 +94,13 @@ export abstract class DateComponent<Props=Dictionary, State=Dictionary> extends
isValidSegDownEl(el: HTMLElement) {
return !(this.props as any).eventDrag && // HACK
!(this.props as any).eventResize && // HACK
!elementClosest(el, '.fc-event-mirror') &&
(this.isPopover() || !this.isInPopover(el))
// ^above line ensures we don't detect a seg interaction within a nested component.
// it's a HACK because it only supports a popover as the nested component.
!elementClosest(el, '.fc-event-mirror')
}

isValidDateDownEl(el: HTMLElement) {
return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
!elementClosest(el, '.fc-daygrid-more-link') && // a "more.." link
!elementClosest(el, 'a[data-navlink]') && // a clickable nav link
!this.isInPopover(el)
}

isPopover() { // HACK. should be overridden by any components that know that they live within a popover
return false
}

isInPopover(el: HTMLElement) {
return Boolean(elementClosest(el, '.fc-popover'))
!elementClosest(el, '.fc-popover') // hack
}
}
51 changes: 24 additions & 27 deletions packages/daygrid/src/MorePopover.tsx
Expand Up @@ -3,13 +3,13 @@ import {
DateMarker,
createElement,
EventInstanceHash,
Hit,
addDays,
DateRange,
getSegMeta,
DayCellRoot,
DayCellContent,
DateProfile,
createRef,
} from '@fullcalendar/common'
import { TableSeg } from './TableSeg'
import { TableBlockEvent } from './TableBlockEvent'
Expand All @@ -30,7 +30,7 @@ export interface MorePopoverProps {
}

export class MorePopover extends DateComponent<MorePopoverProps> {
private popoverEl: HTMLElement
private rootElRef = createRef<HTMLElement>()

render() {
let { options, dateEnv } = this.context
Expand All @@ -39,7 +39,7 @@ export class MorePopover extends DateComponent<MorePopoverProps> {
let title = dateEnv.format(date, options.dayPopoverFormat)

return (
<DayCellRoot date={date} dateProfile={dateProfile} todayRange={todayRange} elRef={this.handlePopoverEl}>
<DayCellRoot date={date} dateProfile={dateProfile} todayRange={todayRange} elRef={this.rootElRef}>
{(rootElRef, dayClassNames, dataAttrs) => (
<Popover
elRef={rootElRef}
Expand Down Expand Up @@ -95,44 +95,41 @@ export class MorePopover extends DateComponent<MorePopoverProps> {
)
}

handlePopoverEl = (popoverEl: HTMLElement | null) => {
this.popoverEl = popoverEl
positionToHit(positionLeft: number, positionTop: number, originEl: HTMLElement) {
let rootEl = this.rootElRef.current

if (popoverEl) {
this.context.registerInteractiveComponent(this, {
el: popoverEl,
useEventCenter: false,
})
} else {
this.context.unregisterInteractiveComponent(this)
if (!originEl || !rootEl) { // why?
return null
}
}

queryHit(positionLeft: number, positionTop: number, elWidth: number, elHeight: number): Hit | null {
let originRect = originEl.getBoundingClientRect()
let elRect = rootEl.getBoundingClientRect()
let newOriginLeft = elRect.left - originRect.left
let newOriginTop = elRect.top - originRect.top
let localLeft = positionLeft - newOriginLeft
let localTop = positionTop - newOriginTop
let date = this.props.date

if (positionLeft < elWidth && positionTop < elHeight) {
if ( // ugly way to detect intersection
localLeft >= 0 && localLeft < elRect.width &&
localTop >= 0 && localTop < elRect.height
) {
return {
component: this,
dateSpan: {
allDay: true,
range: { start: date, end: addDays(date, 1) },
},
dayEl: this.popoverEl,
rect: {
left: 0,
top: 0,
right: elWidth,
bottom: elHeight,
dayEl: rootEl,
relativeRect: {
left: newOriginLeft,
top: newOriginTop,
right: elRect.width,
bottom: elRect.height,
},
layer: 1,
layer: 1, // important when comparing with hits from other components
}
}

return null
}

isPopover() {
return true // gross
}
}
27 changes: 24 additions & 3 deletions packages/daygrid/src/Table.tsx
Expand Up @@ -17,6 +17,7 @@ import {
EventApi,
DateProfile,
Fragment,
createRef,
} from '@fullcalendar/common'
import { TableSeg, splitSegsByRow, splitInteractionByRow } from './TableSeg'
import { TableRow } from './TableRow'
Expand Down Expand Up @@ -54,6 +55,8 @@ interface TableState {

interface MorePopoverState extends MoreLinkArg {
currentFgEventSegs: TableSeg[]
fromRow: number
fromCol: number
}

export class Table extends DateComponent<TableProps, TableState> {
Expand All @@ -65,11 +68,12 @@ export class Table extends DateComponent<TableProps, TableState> {
private splitEventResize = memoize(splitInteractionByRow)
private buildBuildMoreLinkText = memoize(buildBuildMoreLinkText)
private rootEl: HTMLElement
private morePopoverRef = createRef<MorePopover>()
private rowRefs = new RefMap<TableRow>()
private rowPositions: PositionCache
private colPositions: PositionCache

state = {
state: TableState = {
morePopoverState: null,
}

Expand Down Expand Up @@ -153,14 +157,17 @@ export class Table extends DateComponent<TableProps, TableState> {
clientWidth={props.clientWidth}
clientHeight={props.clientHeight}
buildMoreLinkText={buildMoreLinkText}
onMoreClick={this.handleMoreLinkClick}
onMoreClick={(arg) => {
this.handleMoreLinkClick({...arg, fromRow: row})
}}
/>
))}
</tbody>
</table>
{ // clear popover on event mod
(!props.forPrint && morePopoverState && morePopoverState.currentFgEventSegs === props.fgEventSegs) && (
<MorePopover
ref={this.morePopoverRef}
date={morePopoverState.date}
dateProfile={dateProfile}
segs={morePopoverState.allSegs}
Expand Down Expand Up @@ -189,7 +196,7 @@ export class Table extends DateComponent<TableProps, TableState> {
setRef(this.props.elRef, rootEl)
}

handleMoreLinkClick = (arg: MoreLinkArg) => { // TODO: bad names "more link click" versus "more click"
handleMoreLinkClick = (arg: MoreLinkArg & {fromRow: number, fromCol: number}) => { // TODO: bad names "more link click" versus "more click"
let { context } = this
let { dateEnv } = context
let clickOption = context.options.moreLinkClick
Expand Down Expand Up @@ -222,6 +229,8 @@ export class Table extends DateComponent<TableProps, TableState> {
morePopoverState: {
...arg,
currentFgEventSegs: this.props.fgEventSegs,
fromRow: arg.fromRow,
fromCol: arg.fromCol,
},
})
} else if (typeof clickOption === 'string') { // a view name
Expand Down Expand Up @@ -255,6 +264,18 @@ export class Table extends DateComponent<TableProps, TableState> {
}

positionToHit(leftPosition, topPosition) {
let morePopover = this.morePopoverRef.current
let morePopoverHit = morePopover ? morePopover.positionToHit(leftPosition, topPosition, this.rootEl) : null
let { morePopoverState } = this.state

if (morePopoverHit) {
return {
row: morePopoverState.fromRow,
col: morePopoverState.fromCol,
...morePopoverHit,
}
}

let { colPositions, rowPositions } = this
let col = colPositions.leftToIndex(leftPosition)
let row = rowPositions.topToIndex(topPosition)
Expand Down
4 changes: 4 additions & 0 deletions packages/daygrid/src/TableCell.tsx
Expand Up @@ -204,6 +204,10 @@ export class TableCell extends DateComponent<TableCellProps> {
}
}

TableCell.addPropsEquality({
onMoreClick: true, // never forces rerender
})

function renderMoreLinkInner(props) {
return props.text
}
10 changes: 8 additions & 2 deletions packages/daygrid/src/TableRow.tsx
Expand Up @@ -40,7 +40,7 @@ export interface TableRowProps {
dayMaxEventRows: boolean | number
clientWidth: number | null
clientHeight: number | null // simply for causing an updateSize, for when liquid height
onMoreClick?: (arg: MoreLinkArg) => void
onMoreClick?: (arg: MoreLinkArg & {fromCol: number}) => void
dateProfile: DateProfile
todayRange: DateRange
showDayNumbers: boolean
Expand Down Expand Up @@ -133,7 +133,9 @@ export class TableRow extends DateComponent<TableRowProps, TableRowState> {
extraClassNames={cell.extraClassNames}
moreCnt={moreCnts[col]}
buildMoreLinkText={props.buildMoreLinkText}
onMoreClick={props.onMoreClick}
onMoreClick={(arg) => {
props.onMoreClick({...arg, fromCol: col})
}}
segIsHidden={segIsHidden}
moreMarginTop={moreTops[col] /* rename */}
segsByEachCol={segsByEachCol[col]}
Expand Down Expand Up @@ -369,6 +371,10 @@ export class TableRow extends DateComponent<TableRowProps, TableRowState> {
}
}

TableRow.addPropsEquality({
onMoreClick: true, // never forces rerender
})

TableRow.addStateEquality({
segHeights: isPropsEqual,
})

0 comments on commit 878e0de

Please sign in to comment.