Skip to content

Commit

Permalink
better handler typing. move lots of handlers to interaction plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed May 10, 2020
1 parent 0f0c5e9 commit 78ee26f
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 122 deletions.
48 changes: 17 additions & 31 deletions packages/common/src/calendar-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PointerDragEvent } from './interactions/pointer'
import { buildDateSpanApi, DateSpanApi, DatePointApi, DateSpan, buildDatePointApi } from './structs/date-span'
import { buildDateSpanApi, DateSpanApi, DatePointApi, DateSpan } from './structs/date-span'
import { CalendarContext } from './CalendarContext'
import { __assign } from 'tslib'
import { ViewApi } from './ViewApi'
Expand Down Expand Up @@ -27,50 +27,35 @@ export type OptionChangeHandler = (propValue: any, context: CalendarContext) =>
export type OptionChangeHandlerMap = { [propName: string]: OptionChangeHandler }



export interface DateSelectArg extends DateSpanApi {
jsEvent: MouseEvent | null
view: ViewApi
}

export function triggerDateSelect(selection: DateSpan, pev: PointerDragEvent | null, context: CalendarContext & { viewApi?: ViewApi }) {
const arg = {
context.emitter.trigger('select', {
...buildDateSpanApiWithContext(selection, context),
jsEvent: pev ? pev.origEvent as MouseEvent : null, // Is this always a mouse event? See #4655
view: context.viewApi || context.calendarApi.view
}

context.emitter.trigger('select', arg)
} as DateSelectArg)
}



export interface DateUnselectArg {
jsEvent: MouseEvent
view: ViewApi
}

export function triggerDateUnselect(pev: PointerDragEvent | null, context: CalendarContext & { viewApi?: ViewApi }) {
context.emitter.trigger('unselect', {
jsEvent: pev ? pev.origEvent : null,
view: context.viewApi || context.calendarApi.view
})
} as DateUnselectArg)
}


// TODO: receive pev?
export function triggerDateClick(dateSpan: DateSpan, dayEl: HTMLElement, ev: UIEvent, context: CalendarContext & { viewApi?: ViewApi }) {
const arg = {
...buildDatePointApiWithContext(dateSpan, context),
dayEl,
jsEvent: ev as MouseEvent, // Is this always a mouse event? See #4655
view: context.viewApi || context.calendarApi.view
}

context.emitter.trigger('dateClick', arg)
}


export function buildDatePointApiWithContext(dateSpan: DateSpan, context: CalendarContext) {
let props = {} as DatePointApi

for (let transform of context.pluginHooks.datePointTransforms) {
__assign(props, transform(dateSpan, context))
}

__assign(props, buildDatePointApi(dateSpan, context.dateEnv))

return props
}


export function buildDateSpanApiWithContext(dateSpan: DateSpan, context: CalendarContext) {
let props = {} as DateSpanApi
Expand All @@ -85,6 +70,7 @@ export function buildDateSpanApiWithContext(dateSpan: DateSpan, context: Calenda
}



// Given an event's allDay status and start date, return what its fallback end date should be.
// TODO: rename to computeDefaultEventEnd
export function getDefaultEventEnd(allDay: boolean, marker: DateMarker, context: CalendarContext): DateMarker {
Expand Down
10 changes: 9 additions & 1 deletion packages/common/src/interactions/EventClicking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import { EventApi } from '../api/EventApi'
import { elementClosest } from '../util/dom-manip'
import { getElSeg } from '../component/event-rendering'
import { Interaction, InteractionSettings } from './interaction'
import { ViewApi } from '../ViewApi'

export interface EventClickArg {
el: HTMLElement
event: EventApi
jsEvent: MouseEvent
view: ViewApi
}

/*
Detects when the user clicks on an event within a DateComponent
Expand Down Expand Up @@ -44,7 +52,7 @@ export class EventClicking extends Interaction {
),
jsEvent: ev as MouseEvent, // Is this always a mouse event? See #4655
view: context.viewApi
})
} as EventClickArg)

if (url && !ev.defaultPrevented) {
window.location.href = url
Expand Down
10 changes: 9 additions & 1 deletion packages/common/src/interactions/EventHovering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { listenToHoverBySelector } from '../util/dom-event'
import { EventApi } from '../api/EventApi'
import { getElSeg } from '../component/event-rendering'
import { Interaction, InteractionSettings } from './interaction'
import { ViewApi } from '../ViewApi'

export interface EventHoveringArg {
el: HTMLElement
event: EventApi
jsEvent: MouseEvent
view: ViewApi
}

/*
Triggers events and adds/removes core classNames when the user's pointer
Expand Down Expand Up @@ -65,7 +73,7 @@ export class EventHovering extends Interaction {
),
jsEvent: ev as MouseEvent, // Is this always a mouse event? See #4655
view: context.viewApi
})
} as EventHoveringArg)
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,4 @@ export { renderFill, BgEvent, BgEventProps } from './common/bg-fill'
export { WeekNumberRoot, WeekNumberRootProps } from './common/WeekNumberRoot'

export { ViewRoot, ViewRootProps } from './common/ViewRoot'
export { triggerDateSelect, triggerDateClick, buildDatePointApiWithContext, DatePointTransform, DateSpanTransform, DateSelectionApi, getDefaultEventEnd } from './calendar-utils'
export { triggerDateSelect, DatePointTransform, DateSpanTransform, DateSelectionApi, getDefaultEventEnd } from './calendar-utils'
76 changes: 16 additions & 60 deletions packages/common/src/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createDuration, Duration } from './datelib/duration'
import { createDuration } from './datelib/duration'
import { mergeProps } from './util/object'
import { ToolbarInput, CustomButtonInput, ButtonIconsInput, ButtonTextCompoundInput } from './toolbar-parse'
import { createFormatter, FormatterInput } from './datelib/formatting'
Expand All @@ -11,7 +11,6 @@ import { BusinessHoursInput } from './structs/business-hours'
import { ViewApi } from './ViewApi'
import { LocaleSingularArg, RawLocale } from './datelib/locale'
import { OverlapFunc, ConstraintInput, AllowFunc } from './structs/constraint'
import { EventApi } from './api/EventApi'
import { EventInputTransformer } from './structs/event-parse'
import { PluginDef } from './plugin-system-struct'
import { EventSourceInput } from './structs/event-source-parse'
Expand All @@ -23,6 +22,9 @@ import { WeekNumberHookProps } from './common/WeekNumberRoot'
import { SlotLaneHookProps, SlotLabelHookProps, AllDayHookProps, DayHeaderHookProps } from './render-hook-misc'
import { DayCellHookProps } from './common/DayCellRoot'
import { ViewRootHookProps } from './common/ViewRoot'
import { EventClickArg } from './interactions/EventClicking'
import { EventHoveringArg } from './interactions/EventHovering'
import { DateSelectArg, DateUnselectArg } from './calendar-utils'


// base options
Expand Down Expand Up @@ -272,69 +274,23 @@ export const CALENDAR_OPTION_REFINERS = { // does not include base
events: identity as Identity<EventSourceInput>,
eventSources: identity as Identity<EventSourceInput[]>,

datesDidUpdate: identity as Identity<
() => void
>,
windowResize: identity as Identity<
(arg: { view: ViewApi }) => void
>,

// handlers
datesDidUpdate: identity as Identity<() => void>,
windowResize: identity as Identity<(arg: { view: ViewApi }) => void>,
eventClick: identity as Identity<(arg: EventClickArg) => void>, // TODO: resource for scheduler????
eventMouseEnter: identity as Identity<(arg: EventHoveringArg) => void>,
eventMouseLeave: identity as Identity<(arg: EventHoveringArg) => void>,
select: identity as Identity<(arg: DateSelectArg) => void>, // resource for scheduler????
unselect: identity as Identity<(arg: DateUnselectArg) => void>,
loading: identity as Identity<(isLoading: boolean) => void>,

// internal handlers
_destroy: identity as Identity<() => void>,
_init: identity as Identity<() => void>,
_noEventDrop: identity as Identity<() => void>,
_noEventResize: identity as Identity<() => void>,
_resize: identity as Identity<(forced: boolean) => void>,
_scrollRequest: identity as Identity<(arg: any) => void>,

// TODO: move a lot of these to interaction plugin?
dateClick: identity as Identity< // resource for Scheduler
(arg: { date: Date, dateStr: string, allDay: boolean, resource?: any, dayEl: HTMLElement, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventClick: identity as Identity<
(arg: { el: HTMLElement, event: EventApi, jsEvent: MouseEvent, view: ViewApi }) => boolean | void
>,
eventMouseEnter: identity as Identity<
(arg: { el: HTMLElement, event: EventApi, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventMouseLeave: identity as Identity<
(arg: { el: HTMLElement, event: EventApi, jsEvent: MouseEvent, view: ViewApi }) => void
>,
select: identity as Identity< // resource for Scheduler
(arg: { start: Date, end: Date, startStr: string, endStr: string, allDay: boolean, resource?: any, jsEvent: MouseEvent, view: ViewApi }) => void
>,
unselect: identity as Identity<
(arg: { view: ViewApi, jsEvent: Event }) => void
>,
loading: identity as Identity<
(isLoading: boolean) => void
>,
eventDragStart: identity as Identity<
(arg: { event: EventApi, el: HTMLElement, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventDragStop: identity as Identity<
(arg: { event: EventApi, el: HTMLElement, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventDrop: identity as Identity<
(arg: { el: HTMLElement, event: EventApi, oldEvent: EventApi, delta: Duration, revert: () => void, jsEvent: Event, view: ViewApi }) => void
>,
eventResizeStart: identity as Identity<
(arg: { el: HTMLElement, event: EventApi, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventResizeStop: identity as Identity<
(arg: { el: HTMLElement, event: EventApi, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventResize: identity as Identity<
(arg: { el: HTMLElement, startDelta: Duration, endDelta: Duration, prevEvent: EventApi, event: EventApi, revert: () => void, jsEvent: Event, view: ViewApi }) => void
>,
drop: identity as Identity<
(arg: { date: Date, dateStr: string, allDay: boolean, draggedEl: HTMLElement, jsEvent: MouseEvent, view: ViewApi }) => void
>,
eventReceive: identity as Identity<
(arg: { event: EventApi, draggedEl: HTMLElement, view: ViewApi }) => void
>,
eventLeave: identity as Identity<
(arg: { draggedEl: HTMLElement, event: EventApi, view: ViewApi }) => void
>
_scrollRequest: identity as Identity<(arg: any) => void>
}

type BuiltInCalendarOptionRefiners = typeof CALENDAR_OPTION_REFINERS
Expand Down
8 changes: 0 additions & 8 deletions packages/common/src/structs/date-span.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,6 @@ export function buildDateSpanApi(span: DateSpan, dateEnv: DateEnv): DateSpanApi
}
}

export function buildDatePointApi(span: DateSpan, dateEnv: DateEnv): DatePointApi {
return {
date: dateEnv.toDate(span.range.start),
dateStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
allDay: span.allDay
}
}

export function fabricateEventRange(dateSpan: DateSpan, eventUiBases: EventUiHash, context: CalendarContext): EventRenderRange {
let def = parseEventDef(
{ editable: false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import {
ElementDragging,
ViewApi,
CalendarContext,
buildDatePointApiWithContext,
getDefaultEventEnd
} from '@fullcalendar/common'
import { HitDragging } from '../interactions/HitDragging'
import { __assign } from 'tslib'
import { buildDatePointApiWithContext } from '../utils'

export type DragMetaGenerator = DragMetaInput | ((el: HTMLElement) => DragMetaInput)

Expand Down Expand Up @@ -131,13 +131,13 @@ export class ExternalElementDragging {
let finalHit = this.hitDragging.finalHit!
let finalView = finalHit.component.context.viewApi
let dragMeta = this.dragMeta!
let arg = {

receivingContext.emitter.trigger('drop', {
...buildDatePointApiWithContext(finalHit.dateSpan, receivingContext),
draggedEl: pev.subjectEl as HTMLElement,
jsEvent: pev.origEvent as MouseEvent, // Is this always a mouse event? See #4655
view: finalView
}
receivingContext.emitter.trigger('drop', arg)
})

if (dragMeta.create) {
receivingContext.dispatch({
Expand Down
29 changes: 22 additions & 7 deletions packages/interaction/src/interactions/DateClicking.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { PointerDragEvent, Interaction, InteractionSettings, interactionSettingsToStore, triggerDateClick } from '@fullcalendar/common'
import {
PointerDragEvent, Interaction, InteractionSettings, interactionSettingsToStore,
DatePointApi,
ViewApi
} from '@fullcalendar/common'
import { FeaturefulElementDragging } from '../dnd/FeaturefulElementDragging'
import { HitDragging, isHitsEqual } from './HitDragging'
import { buildDatePointApiWithContext } from '../utils'


export interface DateClickArg extends DatePointApi {
dayEl: HTMLElement
jsEvent: MouseEvent
view: ViewApi
}

/*
Monitors when the user clicks on a specific date/time of a component.
Expand Down Expand Up @@ -45,12 +57,15 @@ export class DateClicking extends Interaction {
let { initialHit, finalHit } = this.hitDragging

if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
triggerDateClick(
initialHit.dateSpan,
initialHit.dayEl,
ev.origEvent,
component.context
)
let { context } = component
let arg: DateClickArg = {
...buildDatePointApiWithContext(initialHit.dateSpan, context),
dayEl: initialHit.dayEl,
jsEvent: ev.origEvent as MouseEvent,
view: context.viewApi || context.calendarApi.view
}

context.emitter.trigger('dateClick', arg)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/interaction/src/interactions/DateSelecting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HitDragging } from './HitDragging'
import { FeaturefulElementDragging } from '../dnd/FeaturefulElementDragging'
import { __assign } from 'tslib'


/*
Tracks when the user selects a portion of time of a component,
constituted by a drag over date cells, with a possible delay at the beginning of the drag.
Expand Down
32 changes: 28 additions & 4 deletions packages/interaction/src/interactions/EventDragging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,35 @@ import {
Interaction, InteractionSettings, interactionSettingsStore,
EventDropTransformers,
CalendarContext,
buildDatePointApiWithContext
ViewApi,
Duration
} from '@fullcalendar/common'
import { HitDragging, isHitsEqual } from './HitDragging'
import { FeaturefulElementDragging } from '../dnd/FeaturefulElementDragging'
import { __assign } from 'tslib'
import { buildDatePointApiWithContext } from '../utils'


export type EventDragStopArg = EventDragArg
export type EventDragStartArg = EventDragArg

export interface EventDragArg {
el: HTMLElement
event: EventApi
jsEvent: MouseEvent
view: ViewApi
}

export interface EventDropArg {
el: HTMLElement
delta: Duration
oldEvent: EventApi
event: EventApi
revert: () => void
jsEvent: MouseEvent,
view: ViewApi
// and other "transformed" things
}


export class EventDragging extends Interaction { // TODO: rename to EventSelectingAndDragging
Expand Down Expand Up @@ -121,7 +145,7 @@ export class EventDragging extends Interaction { // TODO: rename to EventSelecti
event: new EventApi(initialContext, eventRange.def, eventRange.instance),
jsEvent: ev.origEvent as MouseEvent, // Is this always a mouse event? See #4655
view: initialContext.viewApi
})
} as EventDragStartArg)
}
}

Expand Down Expand Up @@ -232,7 +256,7 @@ export class EventDragging extends Interaction { // TODO: rename to EventSelecti
event: eventApi,
jsEvent: ev.origEvent as MouseEvent, // Is this always a mouse event? See #4655
view: initialView
})
} as EventDragStopArg)

if (validMutation) {

Expand All @@ -250,7 +274,7 @@ export class EventDragging extends Interaction { // TODO: rename to EventSelecti
__assign(transformed, transformer(validMutation, initialContext))
}

const eventDropArg = {
const eventDropArg: EventDropArg = {
...transformed, // don't use __assign here because it's not type-safe
el: ev.subjectEl as HTMLElement,
delta: validMutation.datesDelta!,
Expand Down

0 comments on commit 78ee26f

Please sign in to comment.