plugin-system.ts 9.6 KB

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