plugin-system.ts 9.5 KB

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