0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-11-22 11:07:57 +01:00
wagtail/client/storybook/StimulusWrapper.tsx
LB Johnston 1da3e5fde7 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 #10197
2023-10-19 07:28:27 +01:00

57 lines
1.6 KiB
TypeScript

import type { Application, Definition } from '@hotwired/stimulus';
import React from 'react';
import { initStimulus } from '../src/includes/initStimulus';
/**
* Wrapper around the Stimulus application to ensure that the application
* is scoped to only the specific story instance's DOM and also ensure
* that the hot-reloader / page switches to not re-instate new applications
* each time.
*
* @example
* import { StimulusWrapper } from '../storybook/StimulusWrapper';
* const Template = ({ debug }) =>
* <StimulusWrapper
* definitions={[{ controllerConstructor: SubmitController, identifier: 'w-something' }]}
* debug={debug}
* >
* <form data-controller="w-something" />
* </StimulusWrapper>
*/
export class StimulusWrapper extends React.Component<{
debug?: boolean;
definitions?: Definition[];
}> {
ref: React.RefObject<HTMLDivElement>;
application?: Application;
constructor(props) {
super(props);
this.ref = React.createRef();
}
componentDidMount() {
const { debug = false, definitions = [] } = this.props;
const root = this.ref.current || document.documentElement;
this.application = initStimulus({ debug, definitions, root });
}
componentDidUpdate({ debug: prevDebug }) {
const { debug } = this.props;
if (debug !== prevDebug) {
Object.assign(this.application as Application, { debug });
}
}
componentWillUnmount() {
if (!this.application) return;
this.application.stop();
delete this.application;
}
render() {
const { children } = this.props;
return <div ref={this.ref}>{children}</div>;
}
}