forked from wagtail/wagtail
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Stimulus util & module export
- Accessing constructor was confusing and createController is not a core requirement - Avoid modifying the base Stimulus application class - Expose `window.StimulusModule` as the module output - Expose `window.wagtail.app` as the Wagtail Stimulus application instance - Rename root element variable to `root` in initStimulus (so we do not conflict with potential action option registration that uses `element` variable names) - Pull in the wagtail.components to the same core.js file and add JSDoc for exposed global - Relates to wagtail#10197
- Loading branch information
1 parent
5c92c8c
commit 1da3e5f
Showing
7 changed files
with
71 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
jest.mock('../..'); | ||
|
||
document.addEventListener = jest.fn(); | ||
|
||
require('./core'); | ||
|
||
describe('core', () => { | ||
const [event] = document.addEventListener.mock.calls[0]; | ||
|
||
it('exposes the Stimulus application instance for reuse', () => { | ||
expect(Object.keys(window.wagtail.app)).toEqual( | ||
expect.arrayContaining(['debug', 'logger']), | ||
); | ||
|
||
expect(window.wagtail.app.load).toBeInstanceOf(Function); | ||
expect(window.wagtail.app.register).toBeInstanceOf(Function); | ||
}); | ||
|
||
it('exposes components for reuse', () => { | ||
expect(Object.keys(window.wagtail.components)).toEqual(['Icon', 'Portal']); | ||
}); | ||
|
||
it('exposes the Stimulus module for reuse', () => { | ||
expect(Object.keys(window.StimulusModule)).toEqual( | ||
expect.arrayContaining(['Application', 'Controller']), | ||
); | ||
}); | ||
|
||
it('DOMContentLoaded', () => { | ||
expect(event).toBe('DOMContentLoaded'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,24 @@ | ||
import type { Definition } from '@hotwired/stimulus'; | ||
import { Application, Controller } from '@hotwired/stimulus'; | ||
|
||
type ControllerObjectDefinition = Record<string, () => void> & { | ||
STATIC?: { | ||
classes?: string[]; | ||
targets?: string[]; | ||
values: typeof Controller.values; | ||
}; | ||
}; | ||
|
||
/** | ||
* Extend the Stimulus application class to provide some convenience | ||
* static attributes or methods to be accessed globally. | ||
*/ | ||
class WagtailApplication extends Application { | ||
/** | ||
* Ensure the base Controller class is available for new controllers. | ||
*/ | ||
static Controller = Controller; | ||
|
||
/** | ||
* Function that accepts a plain old object and returns a Stimulus Controller. | ||
* Useful when ES6 modules with base class being extended not in use | ||
* or build tool not in use or for just super convenient class creation. | ||
* | ||
* Inspired heavily by | ||
* https://github.com/StackExchange/Stacks/blob/v1.6.5/lib/ts/stacks.ts#L84 | ||
* | ||
* @example | ||
* createController({ | ||
* STATIC: { targets = ['container'] } | ||
* connect() { | ||
* console.log('connected', this.element, this.containerTarget); | ||
* } | ||
* }) | ||
* | ||
*/ | ||
static createController = ( | ||
controllerDefinition: ControllerObjectDefinition = {}, | ||
): typeof Controller => { | ||
class NewController<X extends Element> extends Controller<X> {} | ||
|
||
const { STATIC = {}, ...controllerDefinitionWithoutStatic } = | ||
controllerDefinition; | ||
|
||
// set up static values | ||
Object.entries(STATIC).forEach(([key, value]) => { | ||
NewController[key] = value; | ||
}); | ||
|
||
// set up class methods | ||
Object.assign(NewController.prototype, controllerDefinitionWithoutStatic); | ||
|
||
return NewController; | ||
}; | ||
} | ||
import { Application } from '@hotwired/stimulus'; | ||
|
||
/** | ||
* Initialises the Wagtail Stimulus application and dispatches and registers | ||
* custom event behaviour. | ||
* Initialises the Wagtail Stimulus application, loads the provided controller | ||
* definitions and returns the app instance. | ||
* | ||
* Loads the supplied core controller definitions into the application. | ||
* Turns on debug mode if in local development (for now). | ||
* Turns on debug mode if in local development. | ||
*/ | ||
export const initStimulus = ({ | ||
debug = process.env.NODE_ENV === 'development', | ||
definitions = [], | ||
element = document.documentElement, | ||
root = document.documentElement, | ||
}: { | ||
debug?: boolean; | ||
definitions?: Definition[]; | ||
element?: HTMLElement; | ||
root?: HTMLElement; | ||
} = {}): Application => { | ||
const application = WagtailApplication.start(element); | ||
|
||
application.debug = debug; | ||
application.load(definitions); | ||
|
||
return application; | ||
const app = Application.start(root); | ||
app.debug = debug; | ||
app.load(definitions); | ||
return app; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters