initStimulus.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import type { Definition } from '@hotwired/stimulus';
  2. import { Application, Controller } from '@hotwired/stimulus';
  3. type ControllerObjectDefinition = Record<string, () => void> & {
  4. STATIC?: {
  5. classes?: string[];
  6. targets?: string[];
  7. values: typeof Controller.values;
  8. };
  9. };
  10. /**
  11. * Extend the Stimulus application class to provide some convenience
  12. * static attributes or methods to be accessed globally.
  13. */
  14. class WagtailApplication extends Application {
  15. /**
  16. * Ensure the base Controller class is available for new controllers.
  17. */
  18. static Controller = Controller;
  19. /**
  20. * Function that accepts a plain old object and returns a Stimulus Controller.
  21. * Useful when ES6 modules with base class being extended not in use
  22. * or build tool not in use or for just super convenient class creation.
  23. *
  24. * Inspired heavily by
  25. * https://github.com/StackExchange/Stacks/blob/v1.6.5/lib/ts/stacks.ts#L84
  26. *
  27. * @example
  28. * createController({
  29. * STATIC: { targets = ['container'] }
  30. * connect() {
  31. * console.log('connected', this.element, this.containerTarget);
  32. * }
  33. * })
  34. *
  35. */
  36. static createController = (
  37. controllerDefinition: ControllerObjectDefinition = {},
  38. ): typeof Controller => {
  39. class NewController<X extends Element> extends Controller<X> {}
  40. const { STATIC = {}, ...controllerDefinitionWithoutStatic } =
  41. controllerDefinition;
  42. // set up static values
  43. Object.entries(STATIC).forEach(([key, value]) => {
  44. NewController[key] = value;
  45. });
  46. // set up class methods
  47. Object.assign(NewController.prototype, controllerDefinitionWithoutStatic);
  48. return NewController;
  49. };
  50. }
  51. /**
  52. * Initialises the Wagtail Stimulus application and dispatches and registers
  53. * custom event behaviour.
  54. *
  55. * Loads the the supplied core controller definitions into the application.
  56. * Turns on debug mode if in local development (for now).
  57. */
  58. export const initStimulus = ({
  59. debug = process.env.NODE_ENV === 'development',
  60. definitions = [],
  61. element = document.documentElement,
  62. }: {
  63. debug?: boolean;
  64. definitions?: Definition[];
  65. element?: HTMLElement;
  66. } = {}): Application => {
  67. const application = WagtailApplication.start(element);
  68. application.debug = debug;
  69. application.load(definitions);
  70. return application;
  71. };