Adam Shaw 7 lat temu
rodzic
commit
985520cb81
5 zmienionych plików z 77 dodań i 37 usunięć
  1. 20 16
      src/Calendar.ts
  2. 2 1
      src/exports.ts
  3. 17 4
      src/interactions/DateSelecting.ts
  4. 16 5
      src/plugin-system.ts
  5. 22 11
      src/structs/date-span.ts

+ 20 - 16
src/Calendar.ts

@@ -13,7 +13,7 @@ import { DateMarker, startOfDay } from './datelib/marker'
 import { createFormatter } from './datelib/formatting'
 import { Duration, createDuration } from './datelib/duration'
 import reduce from './reducers/main'
-import { parseDateSpan, DateSpanInput, DateSpan, buildDateSpanApi } from './structs/date-span'
+import { parseDateSpan, DateSpanInput, DateSpan, buildDateSpanApi, DateSpanApi, buildDatePointApi, DatePointApi } from './structs/date-span'
 import reselector from './util/reselector'
 import { mapHash, assignTo } from './util/object'
 import { DateRangeInput } from './datelib/date-range'
@@ -33,16 +33,19 @@ import * as exportHooks from './exports'
 import CalendarComponent from './CalendarComponent'
 
 
-export interface DateClickApi {
-  date: Date
-  dateStr: string
-  allDay: boolean
+export interface DateClickApi extends DatePointApi {
   dayEl: HTMLElement
   jsEvent: UIEvent
   view: View
 }
 
+export interface DateSelectionApi extends DateSpanApi {
+  jsEvent: UIEvent
+  view: View
+}
+
 export type dateClickApiTransformer = (dateClick: DateClickApi, dateSpan: DateSpan) => void
+export type dateSelectionApiTransformer = (dateSelection: DateSelectionApi, dateSpan: DateSpan) => void
 
 export default class Calendar {
 
@@ -816,11 +819,15 @@ export default class Calendar {
 
 
   triggerDateSelect(selection: DateSpan, pev?: PointerDragEvent) {
-    let arg = buildDateSpanApi(selection, this.dateEnv)
+    let arg = buildDateSpanApi(selection, this.dateEnv) as DateSelectionApi
 
     arg.jsEvent = pev ? pev.origEvent : null
     arg.view = this.view
 
+    for (let transformer of this.pluginSystem.hooks.dateSelectionApiTransformers) {
+      transformer(arg, selection)
+    }
+
     this.publiclyTrigger('select', [ arg ])
 
     if (pev) {
@@ -841,20 +848,17 @@ export default class Calendar {
 
   // TODO: receive pev?
   triggerDateClick(dateSpan: DateSpan, dayEl: HTMLElement, view: View, ev: UIEvent) {
-    let dateClickApi: DateClickApi = {
-      date: this.dateEnv.toDate(dateSpan.range.start),
-      dateStr: this.dateEnv.formatIso(dateSpan.range.start, { omitTime: dateSpan.allDay }),
-      allDay: dateSpan.allDay,
-      dayEl,
-      jsEvent: ev,
-      view
-    }
+    let arg = buildDatePointApi(dateSpan, this.dateEnv) as DateClickApi
+
+    arg.dayEl = dayEl
+    arg.jsEvent = ev
+    arg.view = view
 
     for (let transformer of this.pluginSystem.hooks.dateClickApiTransformers) {
-      transformer(dateClickApi, dateSpan)
+      transformer(arg, dateSpan)
     }
 
-    this.publiclyTrigger('dateClick', [ dateClickApi ])
+    this.publiclyTrigger('dateClick', [ arg ])
   }
 
 

+ 2 - 1
src/exports.ts

@@ -89,7 +89,7 @@ export { default as ScrollComponent, ScrollbarWidths } from './common/ScrollComp
 export { default as Theme } from './theme/Theme'
 export { default as Component, ComponentContext } from './component/Component'
 export { default as DateComponent, Seg, EventSegUiInteractionState } from './component/DateComponent'
-export { default as Calendar, dateClickApiTransformer, DateClickApi } from './Calendar'
+export { default as Calendar, dateClickApiTransformer, DateClickApi, DateSelectionApi } from './Calendar'
 export { default as View, ViewProps } from './View'
 export { defineView, getViewConfig } from './ViewRegistry'
 export { default as FgEventRenderer } from './component/renderers/FgEventRenderer'
@@ -135,6 +135,7 @@ export { default as Draggable } from './interactions-external/ExternalDraggable'
 export { default as ThirdPartyDraggable } from './interactions-external/ThirdPartyDraggable'
 
 export { Hit } from './interactions/HitDragging'
+export { dateSelectionTransformer } from './interactions/DateSelecting'
 
 export { formatDate, formatRange } from './formatting-api'
 

+ 17 - 4
src/interactions/DateSelecting.ts

@@ -59,10 +59,11 @@ export default class DateSelecting {
     if (hit) {
       dragSelection = computeSelection(
         this.hitDragging.initialHit!.dateSpan,
-        hit.dateSpan
+        hit.dateSpan,
+        calendar.pluginSystem.hooks.dateSelectionTransformers
       )
 
-      if (!this.component.isSelectionValid(dragSelection)) {
+      if (!dragSelection || !this.component.isSelectionValid(dragSelection)) {
         isInvalid = true
         dragSelection = null
       }
@@ -107,7 +108,7 @@ function getComponentTouchDelay(component: DateComponent<any>): number {
   return delay
 }
 
-function computeSelection(dateSpan0: DateSpan, dateSpan1: DateSpan): DateSpan {
+function computeSelection(dateSpan0: DateSpan, dateSpan1: DateSpan, dateSelectionTransformers: dateSelectionTransformer[]): DateSpan {
   let ms = [
     dateSpan0.range.start,
     dateSpan0.range.end,
@@ -117,8 +118,20 @@ function computeSelection(dateSpan0: DateSpan, dateSpan1: DateSpan): DateSpan {
 
   ms.sort(compareNumbers)
 
-  return {
+  let finalDateSpan: DateSpan = {
     range: { start: ms[0], end: ms[3] },
     allDay: dateSpan0.allDay
   }
+
+  for (let transformer of dateSelectionTransformers) {
+    if (
+      !transformer(finalDateSpan, dateSpan0, dateSpan1)
+    ) {
+      return null
+    }
+  }
+
+  return finalDateSpan
 }
+
+export type dateSelectionTransformer = (finalDateSpan: DateSpan, dateSpan0: DateSpan, dateSpan1: DateSpan) => boolean

+ 16 - 5
src/plugin-system.ts

@@ -2,7 +2,8 @@ import { reducerFunc } from './reducers/types'
 import { eventDefParserFunc } from './structs/event'
 import { eventDragMutationMassager } from './interactions/EventDragging'
 import { eventDefMutationApplier } from './structs/event-mutation'
-import { dateClickApiTransformer } from './Calendar'
+import { dateClickApiTransformer, dateSelectionApiTransformer } from './Calendar'
+import { dateSelectionTransformer } from './interactions/DateSelecting'
 
 // TODO: easier way to add new hooks? need to update a million things
 
@@ -11,8 +12,10 @@ export interface PluginDefInput {
   reducers?: reducerFunc[]
   eventDefParsers?: eventDefParserFunc[]
   eventDragMutationMassagers?: eventDragMutationMassager[]
-  eventDefMutationAppliers?: eventDefMutationApplier[],
+  eventDefMutationAppliers?: eventDefMutationApplier[]
+  dateSelectionTransformers?: dateSelectionTransformer[]
   dateClickApiTransformers?: dateClickApiTransformer[]
+  dateSelectionApiTransformers?: dateSelectionApiTransformer[]
 }
 
 export interface PluginHooks {
@@ -20,7 +23,9 @@ export interface PluginHooks {
   eventDefParsers: eventDefParserFunc[]
   eventDragMutationMassagers: eventDragMutationMassager[]
   eventDefMutationAppliers: eventDefMutationApplier[]
+  dateSelectionTransformers: dateSelectionTransformer[]
   dateClickApiTransformers: dateClickApiTransformer[]
+  dateSelectionApiTransformers: dateSelectionApiTransformer[]
 }
 
 export interface PluginDef extends PluginHooks {
@@ -38,7 +43,9 @@ export function createPlugin(input: PluginDefInput): PluginDef {
     eventDefParsers: input.eventDefParsers || [],
     eventDragMutationMassagers: input.eventDragMutationMassagers || [],
     eventDefMutationAppliers: input.eventDefMutationAppliers || [],
-    dateClickApiTransformers: input.dateClickApiTransformers || []
+    dateSelectionTransformers: input.dateSelectionTransformers || [],
+    dateClickApiTransformers: input.dateClickApiTransformers || [],
+    dateSelectionApiTransformers: input.dateSelectionApiTransformers || []
   }
 }
 
@@ -53,7 +60,9 @@ export class PluginSystem {
       eventDefParsers: [],
       eventDragMutationMassagers: [],
       eventDefMutationAppliers: [],
-      dateClickApiTransformers: []
+      dateSelectionTransformers: [],
+      dateClickApiTransformers: [],
+      dateSelectionApiTransformers: []
     }
     this.addedHash = {}
   }
@@ -78,6 +87,8 @@ function combineHooks(hooks0: PluginHooks, hooks1: PluginHooks): PluginHooks {
     eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers),
     eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
     eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
-    dateClickApiTransformers: hooks0.dateClickApiTransformers.concat(hooks1.dateClickApiTransformers)
+    dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
+    dateClickApiTransformers: hooks0.dateClickApiTransformers.concat(hooks1.dateClickApiTransformers),
+    dateSelectionApiTransformers: hooks0.dateSelectionApiTransformers.concat(hooks1.dateSelectionApiTransformers)
   }
 }

+ 22 - 11
src/structs/date-span.ts

@@ -2,7 +2,6 @@ import { DateRange, rangesEqual, OpenDateRange } from '../datelib/date-range'
 import { DateInput, DateEnv } from '../datelib/env'
 import { refineProps } from '../util/misc'
 import { Duration } from '../datelib/duration'
-import { assignTo } from '../util/object'
 import { parseEventDef, createEventInstance } from './event';
 import { computeEventDefUi, EventRenderRange } from '../component/event-rendering';
 import Calendar from '../Calendar'
@@ -39,8 +38,15 @@ export interface DateSpan extends OpenDateSpan {
 export interface DateSpanApi {
   start: Date
   end: Date
+  startStr: string
+  endStr: string
+  allDay: boolean
+}
+
+export interface DatePointApi {
+  date: Date
+  dateStr: string
   allDay: boolean
-  [otherProp: string]: any
 }
 
 const STANDARD_PROPS = {
@@ -134,16 +140,21 @@ export function isSpanPropsMatching(subjectSpan: DateSpan, matchSpan: DateSpan):
 }
 
 export function buildDateSpanApi(span: DateSpan, dateEnv: DateEnv): DateSpanApi {
-  let props = assignTo({}, span)
-  delete props.range
-
-  props.start = dateEnv.toDate(span.range.start)
-  props.end = dateEnv.toDate(span.range.end)
-
-  props.startStr = dateEnv.formatIso(span.range.start, { omitTime: span.allDay })
-  props.endStr = dateEnv.formatIso(span.range.end, { omitTime: span.allDay })
+  return {
+    start: dateEnv.toDate(span.range.start),
+    end: dateEnv.toDate(span.range.end),
+    startStr: dateEnv.formatIso(span.range.start, { omitTime: span.allDay }),
+    endStr: dateEnv.formatIso(span.range.end, { omitTime: span.allDay }),
+    allDay: span.allDay
+  }
+}
 
-  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
+  }
 }
 
 export function fabricateEventRange(dateSpan: DateSpan, calendar: Calendar): EventRenderRange {