Procházet zdrojové kódy

move a lot of stuff into CalendarStateReducer

Adam Shaw před 5 roky
rodič
revize
c19135df1d

+ 3 - 3
packages/__tests__/src/datelib/luxon.js

@@ -90,8 +90,8 @@ describe('luxon plugin', function() {
       })
 
       // hacky way to have a duration parsed
-      let timedDuration = toLuxonDuration(calendar.defaultTimedEventDuration, calendar)
-      let allDayDuration = toLuxonDuration(calendar.defaultAllDayEventDuration, calendar)
+      let timedDuration = toLuxonDuration(calendar.state.computedOptions.defaultTimedEventDuration, calendar)
+      let allDayDuration = toLuxonDuration(calendar.state.computedOptions.defaultAllDayEventDuration, calendar)
 
       expect(timedDuration.as('hours')).toBe(5)
       expect(allDayDuration.as('days')).toBe(3)
@@ -105,7 +105,7 @@ describe('luxon plugin', function() {
       })
 
       // hacky way to have a duration parsed
-      let timedDuration = toLuxonDuration(calendar.defaultTimedEventDuration, calendar)
+      let timedDuration = toLuxonDuration(calendar.state.computedOptions.defaultTimedEventDuration, calendar)
 
       expect(timedDuration.locale).toBe('es')
     })

+ 2 - 2
packages/__tests__/src/datelib/moment.js

@@ -65,8 +65,8 @@ describe('moment plugin', function() {
       })
 
       // hacky way to have a duration parsed
-      let timedDuration = toMomentDuration(calendar.defaultTimedEventDuration)
-      let allDayDuration = toMomentDuration(calendar.defaultAllDayEventDuration)
+      let timedDuration = toMomentDuration(calendar.state.computedOptions.defaultTimedEventDuration)
+      let allDayDuration = toMomentDuration(calendar.state.computedOptions.defaultAllDayEventDuration)
 
       expect(timedDuration.asHours()).toBe(5)
       expect(allDayDuration.asDays()).toBe(3)

+ 18 - 117
packages/core/src/Calendar.tsx

@@ -3,18 +3,15 @@ import { OptionsInput } from './types/input-types'
 import { DateInput } from './datelib/env'
 import { DateMarker, startOfDay } from './datelib/marker'
 import { createFormatter } from './datelib/formatting'
-import { createDuration, DurationInput, Duration } from './datelib/duration'
+import { createDuration, DurationInput } from './datelib/duration'
 import { parseDateSpan, DateSpanInput, DateSpan, buildDateSpanApi, DateSpanApi, buildDatePointApi, DatePointApi } from './structs/date-span'
-import { memoize } from './util/memoize'
-import { mapHash, isPropsEqual } from './util/object'
 import { DateRangeInput } from './datelib/date-range'
-import { EventSourceInput, parseEventSource, EventSourceHash } from './structs/event-source'
-import { EventInput, parseEvent, EventDefHash } from './structs/event'
+import { EventSourceInput, parseEventSource } from './structs/event-source'
+import { EventInput, parseEvent } from './structs/event'
 import { CalendarState, Action } from './reducers/types'
 import { EventSourceApi } from './api/EventSourceApi'
 import { EventApi } from './api/EventApi'
-import { createEmptyEventStore, eventTupleToStore, EventStore } from './structs/event-store'
-import { processScopedUiProps, EventUiHash, EventUi } from './component/event-ui'
+import { eventTupleToStore } from './structs/event-store'
 import { ViewSpec } from './structs/view-spec'
 import { CalendarComponent } from './CalendarComponent'
 import { __assign } from 'tslib'
@@ -30,9 +27,7 @@ import { removeExact } from './util/array'
 import { guid } from './util/misc'
 import { CssDimValue } from './scrollgrid/util'
 import { applyStyleProp } from './util/dom-manip'
-import { ReducerContext } from './reducers/ReducerContext'
 import { CalendarStateReducer } from './reducers/CalendarStateReducer'
-import { parseToolbars } from './toolbar-parse'
 import { getNow } from './reducers/current-date'
 
 
@@ -61,25 +56,6 @@ export type ResizeHandler = (force: boolean) => void
 
 export class Calendar {
 
-  // derived state
-  // TODO: make these all private
-  private buildEventUiSingleBase = memoize(buildEventUiSingleBase)
-  private buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual)
-  private buildEventUiBases = memoize(buildEventUiBases)
-  private renderableEventStore: EventStore
-  public eventUiBases: EventUiHash // needed for validation system
-  public selectionConfig: EventUi // needed for validation system. doesn't need all the info EventUi provides. only validation-related
-  public defaultAllDayEventDuration: Duration
-  public defaultTimedEventDuration: Duration
-  public slotMinTime: Duration
-  public slotMaxTime: Duration
-  private resizeHandlers: ResizeHandler[] = [] // TODO: use emitter somehow?
-  private toolbarConfig
-
-  // interaction
-  calendarInteractions: CalendarInteraction[]
-  interactionsStore: { [componentUid: string]: Interaction[] } = {}
-
   state: CalendarState = {} as any
   isRendering = false
   isRendered = false
@@ -92,6 +68,12 @@ export class Calendar {
   componentRef = createRef<CalendarComponent>()
   view: ViewApi // public API
 
+  // interaction
+  calendarInteractions: CalendarInteraction[]
+  interactionsStore: { [componentUid: string]: Interaction[] } = {}
+
+  private resizeHandlers: ResizeHandler[] = [] // TODO: use emitter somehow?
+
   get component() { return this.componentRef.current } // used to get view-specific business hours :(
 
 
@@ -133,7 +115,6 @@ export class Calendar {
   render() {
     if (!this.isRendering) {
       this.isRendering = true
-      this.renderableEventStore = createEmptyEventStore()
       this.renderRunner.request()
       window.addEventListener('resize', this.handleWindowResize)
     } else {
@@ -170,19 +151,7 @@ export class Calendar {
 
 
   runAction(action: Action) {
-    let oldState = this.state
-    let newState = this.state = this.reducer.reduce(this.state, action, this.emitter, this)
-
-    if (oldState && oldState.options !== newState.options) {
-      this.updateDerivedOptions(newState.options)
-    }
-
-    if ((!oldState || !oldState.loadingLevel) && newState.loadingLevel) {
-      this.emitter.trigger('loading', true)
-
-    } else if ((oldState && oldState.loadingLevel) && !newState.loadingLevel) {
-      this.emitter.trigger('loading', false)
-    }
+    this.state = this.reducer.reduce(this.state, action, this.emitter, this)
   }
 
 
@@ -225,17 +194,6 @@ export class Calendar {
     let { viewType } = state
     let viewSpec = state.viewSpecs[viewType]
 
-    // if event sources are still loading and progressive rendering hasn't been enabled,
-    // keep rendering the last fully loaded set of events
-    let renderableEventStore = this.renderableEventStore =
-      (state.eventSourceLoadingLevel && !this.opt('progressiveEventRendering')) ?
-        this.renderableEventStore :
-        state.eventStore
-
-    let eventUiSingleBase = this.buildEventUiSingleBase(viewSpec.options, this.state)
-    let eventUiBySource = this.buildEventUiBySource(state.eventSources)
-    let eventUiBases = this.eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource)
-
     render(
       <CalendarComponent
         ref={this.componentRef}
@@ -243,15 +201,15 @@ export class Calendar {
         viewSpec={viewSpec}
         dateProfileGenerator={state.dateProfileGenerator}
         dateProfile={state.dateProfile}
-        eventStore={renderableEventStore}
-        eventUiBases={eventUiBases}
+        eventStore={state.renderableEventStore}
+        eventUiBases={state.eventUiBases}
         dateSelection={state.dateSelection}
         eventSelection={state.eventSelection}
         eventDrag={state.eventDrag}
         eventResize={state.eventResize}
         onClassNameChange={this.handleClassNames}
         onHeightChange={this.handleHeightChange}
-        toolbarConfig={this.toolbarConfig}
+        toolbarConfig={state.toolbarConfig}
         emitter={this.emitter}
         calendar={this}
       />,
@@ -353,23 +311,6 @@ export class Calendar {
   }
 
 
-  /*
-  only called when we know options changed
-  */
-  updateDerivedOptions(rawOptions) {
-    this.slotMinTime = createDuration(rawOptions.slotMinTime)
-    this.slotMaxTime = createDuration(rawOptions.slotMaxTime)
-
-    // TODO: don't do every time
-    this.defaultAllDayEventDuration = createDuration(rawOptions.defaultAllDayEventDuration)
-    this.defaultTimedEventDuration = createDuration(rawOptions.defaultTimedEventDuration)
-
-    this.selectionConfig = buildSelectionConfig(rawOptions, this.state)
-
-    this.toolbarConfig = parseToolbars(rawOptions, this.state.theme, rawOptions.direction === 'rtl', this)
-  }
-
-
   getAvailableLocaleCodes() {
     return Object.keys(this.state.availableRawLocales)
   }
@@ -464,8 +405,8 @@ export class Calendar {
   // Given a duration singular unit, like "week" or "day", finds a matching view spec.
   // Preference is given to views that have corresponding buttons.
   getUnitViewSpec(unit: string): ViewSpec | null {
-    let { viewSpecs } = this.state
-    let viewTypes = [].concat(this.toolbarConfig.viewsWithButtons)
+    let { viewSpecs, toolbarConfig } = this.state
+    let viewTypes = [].concat(toolbarConfig.viewsWithButtons)
     let i
     let spec
 
@@ -797,9 +738,9 @@ export class Calendar {
 
     if (allDay) {
       end = startOfDay(end)
-      end = this.state.dateEnv.add(end, this.defaultAllDayEventDuration)
+      end = this.state.dateEnv.add(end, this.state.computedOptions.defaultAllDayEventDuration)
     } else {
-      end = this.state.dateEnv.add(end, this.defaultTimedEventDuration)
+      end = this.state.dateEnv.add(end, this.state.computedOptions.defaultTimedEventDuration)
     }
 
     return end
@@ -991,43 +932,3 @@ export class Calendar {
   }
 
 }
-
-
-
-// for memoizers
-// -----------------------------------------------------------------------------------------------------------------
-
-
-function buildSelectionConfig(rawOptions, context: ReducerContext) {
-  return processScopedUiProps('select', rawOptions, context)
-}
-
-
-function buildEventUiSingleBase(rawOptions, context: ReducerContext) {
-  if (rawOptions.editable) { // so 'editable' affected events
-    rawOptions = { ...rawOptions, eventEditable: true }
-  }
-  return processScopedUiProps('event', rawOptions, context)
-}
-
-
-function buildEventUiBySource(eventSources: EventSourceHash): EventUiHash {
-  return mapHash(eventSources, function(eventSource) {
-    return eventSource.ui
-  })
-}
-
-
-function buildEventUiBases(eventDefs: EventDefHash, eventUiSingleBase: EventUi, eventUiBySource: EventUiHash) {
-  let eventUiBases: EventUiHash = { '': eventUiSingleBase }
-
-  for (let defId in eventDefs) {
-    let def = eventDefs[defId]
-
-    if (def.sourceId && eventUiBySource[def.sourceId]) {
-      eventUiBases[defId] = eventUiBySource[def.sourceId]
-    }
-  }
-
-  return eventUiBases
-}

+ 99 - 12
packages/core/src/reducers/CalendarStateReducer.ts

@@ -7,8 +7,8 @@ import { compileOptions } from '../OptionsManager'
 import { Calendar } from '../Calendar'
 import { StandardTheme } from '../theme/StandardTheme'
 import { EventSourceHash } from '../structs/event-source'
-import { buildViewSpecs, ViewSpecHash } from '../structs/view-spec'
-import { mapHash } from '../util/object'
+import { buildViewSpecs, ViewSpecHash, ViewSpec } from '../structs/view-spec'
+import { mapHash, isPropsEqual } from '../util/object'
 import { DateProfileGenerator } from '../DateProfileGenerator'
 import { reduceViewType } from './view-type'
 import { reduceCurrentDate, getInitialDate, getNow } from './current-date'
@@ -21,6 +21,9 @@ import { reduceEventDrag } from './event-drag'
 import { reduceEventResize } from './event-resize'
 import { Emitter } from '../common/Emitter'
 import { ReducerContext, buildComputedOptions } from './ReducerContext'
+import { processScopedUiProps, EventUiHash, EventUi } from '../component/event-ui'
+import { EventDefHash } from '../structs/event'
+import { parseToolbars } from '../toolbar-parse'
 
 
 export class CalendarStateReducer {
@@ -32,6 +35,10 @@ export class CalendarStateReducer {
   private buildViewSpecs = memoize(buildViewSpecs)
   private buildDateProfileGenerator = memoize(buildDateProfileGenerators)
   private buildComputedOptions = memoize(buildComputedOptions)
+  private buildViewUiProps = memoize(buildViewUiProps)
+  private buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual)
+  private buildEventUiBases = memoize(buildEventUiBases)
+  private parseToolbars = memoize(parseToolbars)
 
 
   reduce(state: CalendarState, action: Action, emitter: Emitter, calendar: Calendar): CalendarState {
@@ -80,13 +87,14 @@ export class CalendarStateReducer {
     let dateProfileGenerators = this.buildDateProfileGenerator(viewSpecs, dateEnv)
     let theme = this.buildTheme(options, pluginHooks)
 
+    let dispatch = state.dispatch || calendar.dispatch.bind(calendar) // will reuse past functions! TODO: memoize? TODO: calendar should bind?
     let reducerContext: ReducerContext = {
       dateEnv,
       options,
       computedOptions: this.buildComputedOptions(options),
       pluginHooks,
       emitter,
-      dispatch: state.dispatch || calendar.dispatch.bind(calendar), // will reuse past functions! TODO: memoize? TODO: calendar should bind?
+      dispatch,
       calendar
     }
 
@@ -99,6 +107,33 @@ export class CalendarStateReducer {
     currentDate = reduceCurrentDate(currentDate, action, dateProfile)
 
     let eventSources = reduceEventSources(state.eventSources, action, dateProfile, reducerContext)
+    let eventSourceLoadingLevel = computeLoadingLevel(eventSources)
+    let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, prevDateEnv, reducerContext)
+
+    let renderableEventStore =
+      (eventSourceLoadingLevel && !options.progressiveEventRendering) ?
+        (state.renderableEventStore || eventStore) : // try from previous state
+        eventStore
+
+    let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(
+      viewSpecs[viewType],
+      dateEnv,
+      pluginHooks,
+      emitter,
+      dispatch,
+      calendar
+    )
+    let eventUiBySource = this.buildEventUiBySource(eventSources)
+    let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource)
+
+    let prevLoadingLevel = state.loadingLevel || 0
+    let loadingLevel = computeLoadingLevel(eventSources)
+
+    if (!prevLoadingLevel && loadingLevel) {
+      emitter.trigger('loading', true)
+    } else if (prevLoadingLevel && !loadingLevel) {
+      emitter.trigger('loading', false)
+    }
 
     let nextState: CalendarState = {
       ...(state as object), // preserve previous state from plugin reducers. tho remove type to make sure all data is provided right now
@@ -113,13 +148,17 @@ export class CalendarStateReducer {
       dateProfile,
       currentDate,
       eventSources,
-      eventStore: reduceEventStore(state.eventStore, action, eventSources, dateProfile, prevDateEnv, reducerContext),
+      eventStore,
+      renderableEventStore,
+      eventSourceLoadingLevel,
+      eventUiBases,
+      selectionConfig,
+      loadingLevel,
       dateSelection: reduceDateSelection(state.dateSelection, action),
       eventSelection: reduceSelectedEvent(state.eventSelection, action),
       eventDrag: reduceEventDrag(state.eventDrag, action),
       eventResize: reduceEventResize(state.eventResize, action),
-      eventSourceLoadingLevel: computeLoadingLevel(eventSources),
-      loadingLevel: computeLoadingLevel(eventSources)
+      toolbarConfig: this.parseToolbars(options, optionOverrides, theme, viewSpecs, calendar)
     }
 
     for (let reducerFunc of pluginHooks.reducers) {
@@ -131,6 +170,19 @@ export class CalendarStateReducer {
 }
 
 
+function computeLoadingLevel(eventSources: EventSourceHash): number {
+  let cnt = 0
+
+  for (let sourceId in eventSources) {
+    if (eventSources[sourceId].isFetching) {
+      cnt++
+    }
+  }
+
+  return cnt
+}
+
+
 function buildDateEnv(
   timeZone: string,
   explicitLocale: string,
@@ -171,14 +223,49 @@ function buildDateProfileGenerators(viewSpecs: ViewSpecHash, dateEnv: DateEnv) {
 }
 
 
-function computeLoadingLevel(eventSources: EventSourceHash): number {
-  let cnt = 0
+function buildViewUiProps(
+  viewSpec: ViewSpec,
+  dateEnv: DateEnv,
+  pluginHooks: PluginHooks,
+  emitter: Emitter,
+  dispatch: (action: Action) => void,
+  calendar: Calendar
+) {
+  let { options } = viewSpec
+  let reducerContext: ReducerContext = {
+    dateEnv,
+    options,
+    computedOptions: buildComputedOptions(options), // bad, REPEAT work
+    pluginHooks,
+    emitter,
+    dispatch,
+    calendar
+  }
 
-  for (let sourceId in eventSources) {
-    if (eventSources[sourceId].isFetching) {
-      cnt++
+  return {
+    eventUiSingleBase: processScopedUiProps('event', options, reducerContext),
+    selectionConfig: processScopedUiProps('select', options, reducerContext)
+  }
+}
+
+
+function buildEventUiBySource(eventSources: EventSourceHash): EventUiHash {
+  return mapHash(eventSources, function(eventSource) {
+    return eventSource.ui
+  })
+}
+
+
+function buildEventUiBases(eventDefs: EventDefHash, eventUiSingleBase: EventUi, eventUiBySource: EventUiHash) {
+  let eventUiBases: EventUiHash = { '': eventUiSingleBase }
+
+  for (let defId in eventDefs) {
+    let def = eventDefs[defId]
+
+    if (def.sourceId && eventUiBySource[def.sourceId]) {
+      eventUiBases[defId] = eventUiBySource[def.sourceId]
     }
   }
 
-  return cnt
+  return eventUiBases
 }

+ 5 - 1
packages/core/src/reducers/ReducerContext.ts

@@ -24,6 +24,8 @@ export interface ComputedOptions {
   defaultTimedEventDuration: Duration
   slotDuration: Duration | null
   snapDuration: Duration | null
+  slotMinTime: Duration
+  slotMaxTime: Duration
 }
 
 export function buildComputedOptions(options: any): ComputedOptions {
@@ -33,6 +35,8 @@ export function buildComputedOptions(options: any): ComputedOptions {
     defaultAllDayEventDuration: createDuration(options.defaultAllDayEventDuration),
     defaultTimedEventDuration: createDuration(options.defaultTimedEventDuration),
     slotDuration: options.slotDuration ? createDuration(options.slotDuration) : null,
-    snapDuration: options.snapDuration ? createDuration(options.snapDuration) : null
+    snapDuration: options.snapDuration ? createDuration(options.snapDuration) : null,
+    slotMinTime: createDuration(options.slotMinTime),
+    slotMaxTime: createDuration(options.slotMaxTime)
   }
 }

+ 1 - 1
packages/core/src/reducers/eventStore.ts

@@ -175,7 +175,7 @@ function applyMutationToRelated(eventStore: EventStore, instanceId: string, muta
       textColor: '',
       classNames: []
     } } as EventUiHash :
-    context.calendar.eventUiBases
+    context.calendar.state.eventUiBases
 
 
   relevant = applyMutationToEventStore(relevant, eventConfigBase, mutation, context)

+ 5 - 0
packages/core/src/reducers/types.ts

@@ -11,15 +11,18 @@ import { RawLocaleMap } from '../datelib/locale'
 import { Theme } from '../theme/Theme'
 import { ViewSpecHash } from '../structs/view-spec'
 import { ReducerContext } from './ReducerContext'
+import { EventUiHash, EventUi } from '../component/event-ui'
 
 export interface CalendarState extends ReducerContext {
   eventSources: EventSourceHash
   eventSourceLoadingLevel: number
+  eventUiBases: EventUiHash
   loadingLevel: number
   viewType: string
   currentDate: DateMarker
   dateProfile: DateProfile | null // for the current view
   eventStore: EventStore
+  renderableEventStore: EventStore
   dateSelection: DateSpan | null
   eventSelection: string
   eventDrag: EventInteractionState | null
@@ -30,6 +33,8 @@ export interface CalendarState extends ReducerContext {
   theme: Theme
   dateProfileGenerator: DateProfileGenerator
   viewSpecs: ViewSpecHash
+  toolbarConfig
+  selectionConfig: EventUi
 }
 
 export type reducerFunc = (state: CalendarState, action: Action, context: ReducerContext) => CalendarState

+ 36 - 12
packages/core/src/toolbar-parse.ts

@@ -1,4 +1,4 @@
-import { ViewSpec } from './structs/view-spec'
+import { ViewSpec, ViewSpecHash } from './structs/view-spec'
 import { Calendar } from './Calendar'
 import { Theme } from './theme/Theme'
 import { mapHash } from './util/object'
@@ -14,28 +14,52 @@ export interface ToolbarWidget {
   buttonText?: any
 }
 
+
 // TODO: make separate parsing of headerToolbar/footerToolbar part of options-processing system
-export function parseToolbars(allOptions, theme: Theme, isRtl: boolean, calendar: Calendar) {
+export function parseToolbars(
+  options: any,
+  optionOverrides: any,
+  theme: Theme,
+  viewSpecs: ViewSpecHash,
+  calendar: Calendar
+) {
   let viewsWithButtons: string[] = []
-  let headerToolbar = allOptions.headerToolbar ? parseToolbar(allOptions.headerToolbar, theme, isRtl, calendar, viewsWithButtons) : null
-  let footerToolbar = allOptions.footerToolbar ? parseToolbar(allOptions.footerToolbar, theme, isRtl, calendar, viewsWithButtons) : null
+  let headerToolbar = options.headerToolbar ? parseToolbar(options.headerToolbar, options, optionOverrides, theme, viewSpecs, calendar, viewsWithButtons) : null
+  let footerToolbar = options.footerToolbar ? parseToolbar(options.footerToolbar, options, optionOverrides, theme, viewSpecs, calendar, viewsWithButtons) : null
 
   return { headerToolbar, footerToolbar, viewsWithButtons }
 }
 
-function parseToolbar(raw, theme: Theme, isRtl: boolean, calendar: Calendar, viewsWithButtons: string[]): ToolbarModel {
-  return mapHash(raw, (rawSection: any) => parseSection(rawSection, theme, isRtl, calendar, viewsWithButtons))
+
+function parseToolbar(
+  sectionStrHash: { [sectionName: string]: string },
+  options: any,
+  optionOverrides: any,
+  theme: Theme,
+  viewSpecs: ViewSpecHash,
+  calendar: Calendar,
+  viewsWithButtons: string[] // dump side effects
+) : ToolbarModel {
+  return mapHash(sectionStrHash, (sectionStr) => parseSection(sectionStr, options, optionOverrides, theme, viewSpecs, calendar, viewsWithButtons))
 }
 
+
 /*
 BAD: querying icons and text here. should be done at render time
 */
-function parseSection(sectionStr: string, theme: Theme, isRtl: boolean, calendar: Calendar, viewsWithButtons: string[]): ToolbarWidget[][] {
-  let calendarState = calendar.state
-  let { viewSpecs } = calendarState
-  let calendarCustomButtons = calendarState.options.customButtons || {}
-  let calendarButtonTextOverrides = calendarState.optionOverrides.buttonText || {}
-  let calendarButtonText = calendarState.options.buttonText || {}
+function parseSection(
+  sectionStr: string,
+  options: any,
+  optionOverrides: any,
+  theme: Theme,
+  viewSpecs: ViewSpecHash,
+  calendar: Calendar,
+  viewsWithButtons: string[] // dump side effects
+): ToolbarWidget[][] {
+  let isRtl = options.direction === 'rtl'
+  let calendarCustomButtons = options.customButtons || {}
+  let calendarButtonTextOverrides = optionOverrides.buttonText || {}
+  let calendarButtonText = options.buttonText || {}
   let sectionSubstrs = sectionStr ? sectionStr.split(' ') : []
 
   return sectionSubstrs.map((buttonGroupStr, i): ToolbarWidget[] => {

+ 3 - 3
packages/core/src/validation.ts

@@ -40,7 +40,7 @@ function isNewPropsValid(newProps, context: ReducerContext) {
     businessHours: viewComponent ? viewComponent.props.businessHours : createEmptyEventStore(), // why? yuck
     dateSelection: '',
     eventStore: calendar.state.eventStore,
-    eventUiBases: calendar.eventUiBases,
+    eventUiBases: calendar.state.eventUiBases,
     eventSelection: '',
     eventDrag: null,
     eventResize: null,
@@ -79,7 +79,7 @@ function isInteractionPropsValid(state: SplittableProps, context: ReducerContext
     subjectDefs,
     interaction.isEvent ?
       state.eventUiBases :
-      { '': calendar.selectionConfig } // if not a real event, validate as a selection
+      { '': calendar.state.selectionConfig } // if not a real event, validate as a selection
   )
 
   if (filterConfig) {
@@ -178,7 +178,7 @@ function isDateSelectionPropsValid(state: SplittableProps, context: ReducerConte
 
   let selection = state.dateSelection
   let selectionRange = selection.range
-  let { selectionConfig } = context.calendar
+  let { selectionConfig } = context.calendar.state
 
   if (filterConfig) {
     selectionConfig = filterConfig(selectionConfig)

+ 1 - 1
packages/interaction/src/interactions/EventDragging.ts

@@ -159,7 +159,7 @@ export class EventDragging extends Interaction { // TODO: rename to EventSelecti
         mutation = computeEventMutation(initialHit, hit, receivingContext.calendar.state.pluginHooks.eventDragMutationMassagers)
 
         if (mutation) {
-          mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.calendar.eventUiBases, mutation, receivingContext)
+          mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.calendar.state.eventUiBases, mutation, receivingContext)
           interaction.mutatedEvents = mutatedRelevantEvents
 
           if (!receivingComponent.isInteractionValid(interaction)) {

+ 1 - 1
packages/interaction/src/interactions/EventResizing.ts

@@ -113,7 +113,7 @@ export class EventResizing extends Interaction {
     }
 
     if (mutation) {
-      mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.calendar.eventUiBases, mutation, context)
+      mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.calendar.state.eventUiBases, mutation, context)
       interaction.mutatedEvents = mutatedRelevantEvents
 
       if (!this.component.isInteractionValid(interaction)) {