import { reducerFunc } from './reducers/types' import { eventDefParserFunc } from './structs/event' import { eventDefMutationApplier } from './structs/event-mutation' import { DatePointTransform, DateSpanTransform, CalendarInteractionClass, OptionChangeHandlerMap } from './calendar-utils' import { ViewConfigInputHash } from './structs/view-config' import { ViewSpec } from './structs/view-spec' import { ViewProps } from './View' import { CalendarComponentProps } from './CalendarComponent' import { ReducerContext } from './reducers/ReducerContext' import { isPropsValidTester } from './validation' import { eventDragMutationMassager, eventIsDraggableTransformer, EventDropTransformers } from './interactions/event-dragging' import { dateSelectionJoinTransformer } from './interactions/date-selecting' import { EventResizeJoinTransforms } from './interactions/event-resizing' import { ExternalDefTransform } from './interactions/external-element-dragging' import { InteractionClass } from './interactions/interaction' import { ThemeClass } from './theme/Theme' import { EventSourceDef } from './structs/event-source' import { CmdFormatterFunc } from './datelib/formatting-cmd' import { RecurringType } from './structs/recurring-event' import { NamedTimeZoneImplClass } from './datelib/timezone' import { ElementDraggingClass } from './interactions/ElementDragging' import { guid } from './util/misc' import { ComponentChildren } from './vdom' import { ScrollGridImpl } from './scrollgrid/ScrollGridImpl' import { ContentTypeHandlers } from './common/render-hook' import { globalPlugins } from './global-plugins' // TODO: easier way to add new hooks? need to update a million things export interface PluginDefInput { deps?: PluginDef[] reducers?: reducerFunc[] eventDefParsers?: eventDefParserFunc[] isDraggableTransformers?: eventIsDraggableTransformer[] eventDragMutationMassagers?: eventDragMutationMassager[] eventDefMutationAppliers?: eventDefMutationApplier[] dateSelectionTransformers?: dateSelectionJoinTransformer[] datePointTransforms?: DatePointTransform[] dateSpanTransforms?: DateSpanTransform[] views?: ViewConfigInputHash viewPropsTransformers?: ViewPropsTransformerClass[] isPropsValid?: isPropsValidTester externalDefTransforms?: ExternalDefTransform[] eventResizeJoinTransforms?: EventResizeJoinTransforms[] viewContainerAppends?: ViewContainerAppend[] eventDropTransformers?: EventDropTransformers[] componentInteractions?: InteractionClass[] calendarInteractions?: CalendarInteractionClass[] themeClasses?: { [themeSystemName: string]: ThemeClass } eventSourceDefs?: EventSourceDef[] cmdFormatter?: CmdFormatterFunc recurringTypes?: RecurringType[] namedTimeZonedImpl?: NamedTimeZoneImplClass initialView?: string elementDraggingImpl?: ElementDraggingClass optionChangeHandlers?: OptionChangeHandlerMap scrollGridImpl?: ScrollGridImpl contentTypeHandlers?: ContentTypeHandlers } export interface PluginHooks { reducers: reducerFunc[] eventDefParsers: eventDefParserFunc[] isDraggableTransformers: eventIsDraggableTransformer[] eventDragMutationMassagers: eventDragMutationMassager[] eventDefMutationAppliers: eventDefMutationApplier[] dateSelectionTransformers: dateSelectionJoinTransformer[] datePointTransforms: DatePointTransform[] dateSpanTransforms: DateSpanTransform[] views: ViewConfigInputHash // TODO: parse before gets to this step? viewPropsTransformers: ViewPropsTransformerClass[] isPropsValid: isPropsValidTester | null externalDefTransforms: ExternalDefTransform[] eventResizeJoinTransforms: EventResizeJoinTransforms[] viewContainerAppends: ViewContainerAppend[] eventDropTransformers: EventDropTransformers[] componentInteractions: InteractionClass[] calendarInteractions: CalendarInteractionClass[] themeClasses: { [themeSystemName: string]: ThemeClass } eventSourceDefs: EventSourceDef[] cmdFormatter?: CmdFormatterFunc recurringTypes: RecurringType[] namedTimeZonedImpl?: NamedTimeZoneImplClass initialView: string elementDraggingImpl?: ElementDraggingClass optionChangeHandlers: OptionChangeHandlerMap scrollGridImpl: ScrollGridImpl | null contentTypeHandlers: ContentTypeHandlers } export interface PluginDef extends PluginHooks { id: string deps: PluginDef[] } export type ViewPropsTransformerClass = new() => ViewPropsTransformer export interface ViewPropsTransformer { transform(viewProps: ViewProps, viewSpec: ViewSpec, calendarProps: CalendarComponentProps, allOptions: any): any } export type ViewContainerAppend = (context: ReducerContext) => ComponentChildren export function createPlugin(input: PluginDefInput): PluginDef { return { id: guid(), deps: input.deps || [], reducers: input.reducers || [], eventDefParsers: input.eventDefParsers || [], isDraggableTransformers: input.isDraggableTransformers || [], eventDragMutationMassagers: input.eventDragMutationMassagers || [], eventDefMutationAppliers: input.eventDefMutationAppliers || [], dateSelectionTransformers: input.dateSelectionTransformers || [], datePointTransforms: input.datePointTransforms || [], dateSpanTransforms: input.dateSpanTransforms || [], views: input.views || {}, viewPropsTransformers: input.viewPropsTransformers || [], isPropsValid: input.isPropsValid || null, externalDefTransforms: input.externalDefTransforms || [], eventResizeJoinTransforms: input.eventResizeJoinTransforms || [], viewContainerAppends: input.viewContainerAppends || [], eventDropTransformers: input.eventDropTransformers || [], componentInteractions: input.componentInteractions || [], calendarInteractions: input.calendarInteractions || [], themeClasses: input.themeClasses || {}, eventSourceDefs: input.eventSourceDefs || [], cmdFormatter: input.cmdFormatter, recurringTypes: input.recurringTypes || [], namedTimeZonedImpl: input.namedTimeZonedImpl, initialView: input.initialView || '', elementDraggingImpl: input.elementDraggingImpl, optionChangeHandlers: input.optionChangeHandlers || {}, scrollGridImpl: input.scrollGridImpl || null, contentTypeHandlers: input.contentTypeHandlers || {} } } export function buildPluginHooks(pluginDefs?: PluginDef[]): PluginHooks { let isAdded: { [pluginId: string]: boolean } = {} let hooks: PluginHooks = { reducers: [], eventDefParsers: [], isDraggableTransformers: [], eventDragMutationMassagers: [], eventDefMutationAppliers: [], dateSelectionTransformers: [], datePointTransforms: [], dateSpanTransforms: [], views: {}, viewPropsTransformers: [], isPropsValid: null, externalDefTransforms: [], eventResizeJoinTransforms: [], viewContainerAppends: [], eventDropTransformers: [], componentInteractions: [], calendarInteractions: [], themeClasses: {}, eventSourceDefs: [], cmdFormatter: null, recurringTypes: [], namedTimeZonedImpl: null, initialView: '', elementDraggingImpl: null, optionChangeHandlers: {}, scrollGridImpl: null, contentTypeHandlers: {} } function addDefs(defs: PluginDef[]) { for (let def of defs) { if (!isAdded[def.id]) { isAdded[def.id] = true addDefs(def.deps) hooks = combineHooks(hooks, def) } } } addDefs(globalPlugins) if (pluginDefs) { addDefs(pluginDefs) } return hooks } function combineHooks(hooks0: PluginHooks, hooks1: PluginHooks): PluginHooks { return { reducers: hooks0.reducers.concat(hooks1.reducers), eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers), isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers), eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers), eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers), dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers), datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms), dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms), views: { ...hooks0.views, ...hooks1.views }, viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers), isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid, externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms), eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms), viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends), eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers), calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions), componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions), themeClasses: { ...hooks0.themeClasses, ...hooks1.themeClasses }, eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs), cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter, recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes), namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl, initialView: hooks0.initialView || hooks1.initialView, // put earlier plugins FIRST elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, // " optionChangeHandlers: { ...hooks0.optionChangeHandlers, ...hooks1.optionChangeHandlers }, scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl, contentTypeHandlers: { ...hooks0.contentTypeHandlers, ...hooks1.contentTypeHandlers } } }