plugin-system.ts 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import { reducerFunc } from './reducers/types'
  2. import { eventDefParserFunc } from './structs/event'
  3. import { eventDefMutationApplier } from './structs/event-mutation'
  4. import { DatePointTransform, DateSpanTransform, CalendarInteractionClass, OptionChangeHandlerMap } from './calendar-utils'
  5. import { ViewConfigInputHash } from './structs/view-config'
  6. import { ViewSpec } from './structs/view-spec'
  7. import { ViewProps } from './View'
  8. import { CalendarComponentProps } from './CalendarComponent'
  9. import { ReducerContext } from './reducers/ReducerContext'
  10. import { isPropsValidTester } from './validation'
  11. import { eventDragMutationMassager, eventIsDraggableTransformer, EventDropTransformers } from './interactions/event-dragging'
  12. import { dateSelectionJoinTransformer } from './interactions/date-selecting'
  13. import { EventResizeJoinTransforms } from './interactions/event-resizing'
  14. import { ExternalDefTransform } from './interactions/external-element-dragging'
  15. import { InteractionClass } from './interactions/interaction'
  16. import { ThemeClass } from './theme/Theme'
  17. import { EventSourceDef } from './structs/event-source'
  18. import { CmdFormatterFunc } from './datelib/formatting-cmd'
  19. import { RecurringType } from './structs/recurring-event'
  20. import { NamedTimeZoneImplClass } from './datelib/timezone'
  21. import { ElementDraggingClass } from './interactions/ElementDragging'
  22. import { guid } from './util/misc'
  23. import { ComponentChildren } from './vdom'
  24. import { ScrollGridImpl } from './scrollgrid/ScrollGridImpl'
  25. import { ContentTypeHandlers } from './common/render-hook'
  26. import { globalPlugins } from './global-plugins'
  27. // TODO: easier way to add new hooks? need to update a million things
  28. export interface PluginDefInput {
  29. deps?: PluginDef[]
  30. reducers?: reducerFunc[]
  31. eventDefParsers?: eventDefParserFunc[]
  32. isDraggableTransformers?: eventIsDraggableTransformer[]
  33. eventDragMutationMassagers?: eventDragMutationMassager[]
  34. eventDefMutationAppliers?: eventDefMutationApplier[]
  35. dateSelectionTransformers?: dateSelectionJoinTransformer[]
  36. datePointTransforms?: DatePointTransform[]
  37. dateSpanTransforms?: DateSpanTransform[]
  38. views?: ViewConfigInputHash
  39. viewPropsTransformers?: ViewPropsTransformerClass[]
  40. isPropsValid?: isPropsValidTester
  41. externalDefTransforms?: ExternalDefTransform[]
  42. eventResizeJoinTransforms?: EventResizeJoinTransforms[]
  43. viewContainerAppends?: ViewContainerAppend[]
  44. eventDropTransformers?: EventDropTransformers[]
  45. componentInteractions?: InteractionClass[]
  46. calendarInteractions?: CalendarInteractionClass[]
  47. themeClasses?: { [themeSystemName: string]: ThemeClass }
  48. eventSourceDefs?: EventSourceDef[]
  49. cmdFormatter?: CmdFormatterFunc
  50. recurringTypes?: RecurringType[]
  51. namedTimeZonedImpl?: NamedTimeZoneImplClass
  52. initialView?: string
  53. elementDraggingImpl?: ElementDraggingClass
  54. optionChangeHandlers?: OptionChangeHandlerMap
  55. scrollGridImpl?: ScrollGridImpl
  56. contentTypeHandlers?: ContentTypeHandlers
  57. }
  58. export interface PluginHooks {
  59. reducers: reducerFunc[]
  60. eventDefParsers: eventDefParserFunc[]
  61. isDraggableTransformers: eventIsDraggableTransformer[]
  62. eventDragMutationMassagers: eventDragMutationMassager[]
  63. eventDefMutationAppliers: eventDefMutationApplier[]
  64. dateSelectionTransformers: dateSelectionJoinTransformer[]
  65. datePointTransforms: DatePointTransform[]
  66. dateSpanTransforms: DateSpanTransform[]
  67. views: ViewConfigInputHash // TODO: parse before gets to this step?
  68. viewPropsTransformers: ViewPropsTransformerClass[]
  69. isPropsValid: isPropsValidTester | null
  70. externalDefTransforms: ExternalDefTransform[]
  71. eventResizeJoinTransforms: EventResizeJoinTransforms[]
  72. viewContainerAppends: ViewContainerAppend[]
  73. eventDropTransformers: EventDropTransformers[]
  74. componentInteractions: InteractionClass[]
  75. calendarInteractions: CalendarInteractionClass[]
  76. themeClasses: { [themeSystemName: string]: ThemeClass }
  77. eventSourceDefs: EventSourceDef[]
  78. cmdFormatter?: CmdFormatterFunc
  79. recurringTypes: RecurringType[]
  80. namedTimeZonedImpl?: NamedTimeZoneImplClass
  81. initialView: string
  82. elementDraggingImpl?: ElementDraggingClass
  83. optionChangeHandlers: OptionChangeHandlerMap
  84. scrollGridImpl: ScrollGridImpl | null
  85. contentTypeHandlers: ContentTypeHandlers
  86. }
  87. export interface PluginDef extends PluginHooks {
  88. id: string
  89. deps: PluginDef[]
  90. }
  91. export type ViewPropsTransformerClass = new() => ViewPropsTransformer
  92. export interface ViewPropsTransformer {
  93. transform(viewProps: ViewProps, viewSpec: ViewSpec, calendarProps: CalendarComponentProps, allOptions: any): any
  94. }
  95. export type ViewContainerAppend = (context: ReducerContext) => ComponentChildren
  96. export function createPlugin(input: PluginDefInput): PluginDef {
  97. return {
  98. id: guid(),
  99. deps: input.deps || [],
  100. reducers: input.reducers || [],
  101. eventDefParsers: input.eventDefParsers || [],
  102. isDraggableTransformers: input.isDraggableTransformers || [],
  103. eventDragMutationMassagers: input.eventDragMutationMassagers || [],
  104. eventDefMutationAppliers: input.eventDefMutationAppliers || [],
  105. dateSelectionTransformers: input.dateSelectionTransformers || [],
  106. datePointTransforms: input.datePointTransforms || [],
  107. dateSpanTransforms: input.dateSpanTransforms || [],
  108. views: input.views || {},
  109. viewPropsTransformers: input.viewPropsTransformers || [],
  110. isPropsValid: input.isPropsValid || null,
  111. externalDefTransforms: input.externalDefTransforms || [],
  112. eventResizeJoinTransforms: input.eventResizeJoinTransforms || [],
  113. viewContainerAppends: input.viewContainerAppends || [],
  114. eventDropTransformers: input.eventDropTransformers || [],
  115. componentInteractions: input.componentInteractions || [],
  116. calendarInteractions: input.calendarInteractions || [],
  117. themeClasses: input.themeClasses || {},
  118. eventSourceDefs: input.eventSourceDefs || [],
  119. cmdFormatter: input.cmdFormatter,
  120. recurringTypes: input.recurringTypes || [],
  121. namedTimeZonedImpl: input.namedTimeZonedImpl,
  122. initialView: input.initialView || '',
  123. elementDraggingImpl: input.elementDraggingImpl,
  124. optionChangeHandlers: input.optionChangeHandlers || {},
  125. scrollGridImpl: input.scrollGridImpl || null,
  126. contentTypeHandlers: input.contentTypeHandlers || {}
  127. }
  128. }
  129. export function buildPluginHooks(pluginDefs?: PluginDef[]): PluginHooks {
  130. let isAdded: { [pluginId: string]: boolean } = {}
  131. let hooks: PluginHooks = {
  132. reducers: [],
  133. eventDefParsers: [],
  134. isDraggableTransformers: [],
  135. eventDragMutationMassagers: [],
  136. eventDefMutationAppliers: [],
  137. dateSelectionTransformers: [],
  138. datePointTransforms: [],
  139. dateSpanTransforms: [],
  140. views: {},
  141. viewPropsTransformers: [],
  142. isPropsValid: null,
  143. externalDefTransforms: [],
  144. eventResizeJoinTransforms: [],
  145. viewContainerAppends: [],
  146. eventDropTransformers: [],
  147. componentInteractions: [],
  148. calendarInteractions: [],
  149. themeClasses: {},
  150. eventSourceDefs: [],
  151. cmdFormatter: null,
  152. recurringTypes: [],
  153. namedTimeZonedImpl: null,
  154. initialView: '',
  155. elementDraggingImpl: null,
  156. optionChangeHandlers: {},
  157. scrollGridImpl: null,
  158. contentTypeHandlers: {}
  159. }
  160. function addDefs(defs: PluginDef[]) {
  161. for (let def of defs) {
  162. if (!isAdded[def.id]) {
  163. isAdded[def.id] = true
  164. addDefs(def.deps)
  165. hooks = combineHooks(hooks, def)
  166. }
  167. }
  168. }
  169. addDefs(globalPlugins)
  170. if (pluginDefs) {
  171. addDefs(pluginDefs)
  172. }
  173. return hooks
  174. }
  175. function combineHooks(hooks0: PluginHooks, hooks1: PluginHooks): PluginHooks {
  176. return {
  177. reducers: hooks0.reducers.concat(hooks1.reducers),
  178. eventDefParsers: hooks0.eventDefParsers.concat(hooks1.eventDefParsers),
  179. isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
  180. eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
  181. eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
  182. dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
  183. datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
  184. dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
  185. views: { ...hooks0.views, ...hooks1.views },
  186. viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
  187. isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
  188. externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
  189. eventResizeJoinTransforms: hooks0.eventResizeJoinTransforms.concat(hooks1.eventResizeJoinTransforms),
  190. viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
  191. eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
  192. calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
  193. componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
  194. themeClasses: { ...hooks0.themeClasses, ...hooks1.themeClasses },
  195. eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
  196. cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
  197. recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
  198. namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
  199. initialView: hooks0.initialView || hooks1.initialView, // put earlier plugins FIRST
  200. elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl, // "
  201. optionChangeHandlers: { ...hooks0.optionChangeHandlers, ...hooks1.optionChangeHandlers },
  202. scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
  203. contentTypeHandlers: { ...hooks0.contentTypeHandlers, ...hooks1.contentTypeHandlers }
  204. }
  205. }