Преглед изворни кода

better handler typing. move lots of handlers to interaction plugin

Adam Shaw пре 5 година
родитељ
комит
78ee26f73c

+ 17 - 31
packages/common/src/calendar-utils.ts

@@ -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'
@@ -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
@@ -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 {

+ 9 - 1
packages/common/src/interactions/EventClicking.ts

@@ -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
@@ -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

+ 9 - 1
packages/common/src/interactions/EventHovering.ts

@@ -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
@@ -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)
     }
   }
 

+ 1 - 1
packages/common/src/main.ts

@@ -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'

+ 16 - 60
packages/common/src/options.ts

@@ -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'
@@ -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'
@@ -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
@@ -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

+ 0 - 8
packages/common/src/structs/date-span.ts

@@ -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 },

+ 4 - 4
packages/interaction/src/interactions-external/ExternalElementDragging.ts

@@ -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)
 
@@ -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({

+ 22 - 7
packages/interaction/src/interactions/DateClicking.ts

@@ -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.
@@ -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)
       }
     }
   }

+ 1 - 0
packages/interaction/src/interactions/DateSelecting.ts

@@ -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.

+ 28 - 4
packages/interaction/src/interactions/EventDragging.ts

@@ -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
@@ -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)
     }
   }
 
@@ -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) {
 
@@ -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!,

+ 26 - 4
packages/interaction/src/interactions/EventResizing.ts

@@ -11,13 +11,35 @@ import {
   createDuration,
   EventInteractionState,
   EventResizeJoinTransforms,
-  Interaction, InteractionSettings, interactionSettingsToStore
+  Interaction, InteractionSettings, interactionSettingsToStore, ViewApi, Duration
 } from '@fullcalendar/common'
 import { HitDragging, isHitsEqual } from './HitDragging'
 import { FeaturefulElementDragging } from '../dnd/FeaturefulElementDragging'
 import { __assign } from 'tslib'
 
 
+export type EventResizeStartArg = EventResizeStartStopArg
+export type EventResizeStopArg = EventResizeStartStopArg
+
+export interface EventResizeStartStopArg {
+  el: HTMLElement
+  event: EventApi
+  jsEvent: MouseEvent
+  view: ViewApi
+}
+
+export interface EventResizeDoneArg {
+  el: HTMLElement
+  startDelta: Duration
+  endDelta: Duration
+  prevEvent: EventApi
+  event: EventApi
+  revert: () => void
+  jsEvent: MouseEvent
+  view: ViewApi
+}
+
+
 export class EventResizing extends Interaction {
 
   dragging: FeaturefulElementDragging
@@ -85,7 +107,7 @@ export class EventResizing extends Interaction {
       event: new EventApi(context, eventRange.def, eventRange.instance),
       jsEvent: ev.origEvent as MouseEvent, // Is this always a mouse event? See #4655
       view: context.viewApi
-    })
+    } as EventResizeStartArg)
   }
 
   handleHitUpdate = (hit: Hit | null, isFinal: boolean, ev: PointerDragEvent) => {
@@ -164,7 +186,7 @@ export class EventResizing extends Interaction {
       event: eventApi,
       jsEvent: ev.origEvent as MouseEvent, // Is this always a mouse event? See #4655
       view: context.viewApi
-    })
+    } as EventResizeStopArg)
 
     if (this.validMutation) {
       context.dispatch({
@@ -190,7 +212,7 @@ export class EventResizing extends Interaction {
         },
         jsEvent: ev.origEvent,
         view: context.viewApi
-      })
+      } as EventResizeDoneArg)
 
     } else {
       context.emitter.trigger('_noEventResize')

+ 3 - 1
packages/interaction/src/main.ts

@@ -5,11 +5,13 @@ import { EventDragging } from './interactions/EventDragging'
 import { EventResizing } from './interactions/EventResizing'
 import { UnselectAuto } from './interactions/UnselectAuto'
 import { FeaturefulElementDragging } from './dnd/FeaturefulElementDragging'
+import { OPTION_REFINERS } from './options'
 
 export default createPlugin({
   componentInteractions: [ DateClicking, DateSelecting, EventDragging, EventResizing ],
   calendarInteractions: [ UnselectAuto ],
-  elementDraggingImpl: FeaturefulElementDragging
+  elementDraggingImpl: FeaturefulElementDragging,
+  optionRefiners: OPTION_REFINERS
 })
 
 export { FeaturefulElementDragging }

+ 26 - 0
packages/interaction/src/options.ts

@@ -0,0 +1,26 @@
+import { identity, Identity } from '@fullcalendar/common'
+import { DateClickArg } from './interactions/DateClicking'
+import { EventDragStartArg, EventDragStopArg, EventDropArg } from './interactions/EventDragging'
+import { EventResizeStartArg, EventResizeStopArg, EventResizeDoneArg } from './interactions/EventResizing'
+import { DropArg, EventReceiveArg, EventLeaveArg } from './utils'
+
+
+export const OPTION_REFINERS = {
+  dateClick: identity as Identity<(arg: DateClickArg) => void>,
+  eventDragStart: identity as Identity<(arg: EventDragStartArg) => void>,
+  eventDragStop: identity as Identity<(arg: EventDragStopArg) => void>,
+  eventDrop: identity as Identity<(arg: EventDropArg) => void>,
+  eventResizeStart: identity as Identity<(arg: EventResizeStartArg) => void>,
+  eventResizeStop: identity as Identity<(arg: EventResizeStopArg) => void>,
+  eventResize: identity as Identity<(arg: EventResizeDoneArg) => void>,
+  drop: identity as Identity<(arg: DropArg) => void>,
+  eventReceive: identity as Identity<(arg: EventReceiveArg) => void>,
+  eventLeave: identity as Identity<(arg: EventLeaveArg) => void>,
+}
+
+
+// add types
+type ExtarOptionRefiners = typeof OPTION_REFINERS
+declare module '@fullcalendar/common' {
+  interface BaseOptionRefiners extends ExtarOptionRefiners {}
+}

+ 40 - 0
packages/interaction/src/utils.ts

@@ -0,0 +1,40 @@
+import { DateSpan, CalendarContext, DatePointApi, DateEnv, ViewApi, EventApi } from '@fullcalendar/common'
+import { __assign } from 'tslib'
+
+
+export interface DropArg extends DatePointApi {
+  draggedEl: HTMLElement
+  jsEvent: MouseEvent
+  view: ViewApi
+}
+
+
+export type EventReceiveArg = EventReceiveLeaveArg
+export type EventLeaveArg = EventReceiveLeaveArg
+export interface EventReceiveLeaveArg { // will this become public?
+  draggedEl: HTMLElement
+  event: EventApi
+  view: ViewApi
+}
+
+
+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 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
+  }
+}