docs: extensions (#1258)

* docs: process docs to include UX Stories requirement

* docs: include note regarding different environments

* Services init

* Remove unused canny logos

* docs: add ModalService diagram

* docs: GIF of notification

* docs: add ui-services page

* docs: simplify ui services call out in the general services docs

* docs: tips and tricks for UI services

* docs: moar pages

* docs: dialog gif

* docs: services in summary/sidebar

* docs: gif examples at top of dialog and notification pages

* docs: add UIModal gif

* docs: details for Dialog Service

* docs: include usage information for ui modal service

* docs: detailed information about our UI Notification Service

* docs: services diagram

* docs: remove unused links

* docs: services example and image

* docs: stubbing extension pages

* docs: UX Stories --> User Cases

* chore: eslint fix

* docs: extensions overview + diagram

* docs: update extensions in sidebar

* docs: extension skeleton and registration info

* docs: copy of maintained extensions table partial in the extensions folder

* docs: swap out old extensions structure for new
This commit is contained in:
Danny Brown 2019-12-06 16:31:46 -05:00 committed by GitHub
parent fd1d29820a
commit 02572b4928
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 380 additions and 282 deletions

View File

@ -3,7 +3,7 @@
- [ ] Brief description of changes
- [ ] Links to any relevant issues
- [ ] Required status checks are passing
- [ ] UX Stories if changes impact the user's experience
- [ ] User cases if changes impact the user's experience
- [ ] `@mention` a maintainer to request a review
<!--

View File

@ -21,11 +21,18 @@
- [Extensions](advanced/architecture.md#misc-extensions)
- [Diagram](advanced/architecture.md#diagram)
- [Common Questions](advanced/architecture.md#common-questions)
- [Extensions](advanced/extensions.md)
- [Overview](advanced/extensions.md#overview)
- [Modules](advanced/extensions.md#modules)
- [Registering](advanced/extensions.md#registering-extensions)
- [OHIF Maintained](advanced/extensions.md#ohif-maintained-extensions)
- [Extensions](extensions/index.md)
- [Registering](extensions/index.md#registering-an-extension)
- [Lifecycle Hooks](extensions/index.md#lifecycle-hooks)
- [preRegistration](extensions/lifecycle/pre-registration.md)
- [Modules](extensions/index.md#modules)
- [Commands](extensions/modules/commands.md)
- [Panel](extensions/modules/panel.md)
- [SOP Class Handler](extensions/modules/sop-class-handler.md)
- [Toolbar](extensions/modules/toolbar.md)
- [Viewport](extensions/modules/viewport.md)
- [Contexts](extension/index.md#contexts)
- [OHIF Maintained](extension/index.md#maintained-extensions)
- [Services](services/index.md)
- [Default](services/default/index.md)
- [UI](services/ui/index.md)

View File

@ -94,16 +94,16 @@ the viewer. Some common use cases include:
- Adding surgical templating tools and reports
- and many others
We expose common integration points via [extensions](./extensions.md) to make
this possible. The viewer and many of our own extensions also offer
We expose common integration points via [extensions](../extensions/index.md) to
make this possible. The viewer and many of our own extensions also offer
[configuration][configuration]. For a list of extensions maintained by OHIF,
[check out this helpful table](./extensions.html#ohif-maintained-extensions).
[check out this helpful table](../extensions/index.mdl#maintained-extensions).
If you find yourself thinking "I wish the Viewer could do X", and you can't
accomplish it with an extension today, create a GitHub issue! We're actively
looking for ways to improve our extensibility ^\_^
[Click here to read more about extensions!](./extensions.md)
[Click here to read more about extensions!](../extensions/index.md)
### Diagram
@ -145,7 +145,7 @@ you would need to recreate.
[viewer-npm]: https://www.npmjs.com/package/@ohif/viewer
[pwa]: https://developers.google.com/web/progressive-web-apps/
[configuration]: ../essentials/configuration.md
[extensions]: ./extensions.md
[extensions]: ../extensions/index.md
[core-github]: https://github.com/OHIF/viewers/platform/core
[ui-github]: https://github.com/OHIF/Viewers/platform/ui
<!-- prettier-ignore-end -->

View File

@ -2,7 +2,8 @@
This is not yet exposed in an easy/convenient way. Most tools are currently
added by creating new Viewport, Toolbar, and SOPInstanceHandler extension
modules. You can read more about that approach in [extensions](./extensions.md).
modules. You can read more about that approach in
[extensions](../extensions/index.md).
In the near future, we intend to improve the extensibility of tools for existing
Viewports (like our Cornerstone.js and VTK.js viewports).

View File

@ -1,263 +0,0 @@
# Extensions
Extensions add new functionality to the viewer by registering one or more
modules. They go one step further than configuration in that they allow us to
inject custom React components, so long as they adhere to the module's
interface. This can be something as simple as adding a new button to the
toolbar, or as complex as a new viewport capable of rendering volumes in 3D.
- [Overview](#overview)
- [Modules](#modules)
- [Commands](#commands)
- [Hotkeys](#hotkeys)
- [Toolbar](#toolbar)
- [Panel](#panel)
- [Viewport](#viewport)
- [SOP Class Handler](#sopclasshandler)
## Overview
At a glance, an extension is a javascript object that has an `id` property, and
one or more "module" methods. You can find an abbreviated extension below, or
[view the source][example-ext-src] of our example extension.
```js
export default {
/**
* Only required property. Should be a unique value across all extensions.
*/
id: 'example-extension',
/**
* Registers one or more named commands scoped to a context. Commands are
* the primary means for...
*/
getCommandsModule() {
return {
defaultContext: 'VIEWER'
actions: { ... },
definitions: { ... }
}
},
/**
* Allows you to provide toolbar definitions that will be merged with any
* existing application toolbar configuration. Used to determine which
* buttons should be visible when, their order, what happens when they're
* clicked, etc.
*/
getToolbarModule() {
return {
definitions: [ ... ],
defaultContext: 'ACTIVE_VIEWPORT::CORNERSTONE'
}
}
/**
* Not yet implemented
*/
getPanelModule: () => null,
/**
* Registers a ReactComponent that should be used to render data in a
* Viewport. The first registered viewport is our "default viewport". If
* more than one viewport is registered, we use `SopClassHandlers` to
* determine which viewport should be used.
*/
getViewportModule: () => reactViewportComponent,
/** Provides a whitelist of SOPClassUIDs the viewport is capable of rendering.
* Can modify default behavior for methods like `getDisplaySetFromSeries` */
getSopClassHandler: () => {
id: 'some-other-unique-id',
sopClassUids: [ ... ],
getDisplaySetFromSeries: (series, study, dicomWebClient, authorizationHeaders) => { ... }
},
}
```
### Modules
There are a few different module types. Each module type allows us to extend the
viewer in a different way, and provides a consistent API for us to do so. You
can find a full list of the different types of modules
[`in ohif-core`][module-types]. Information on each type of module, it's API,
and how we determine when/where it should be used is included below.
> NOTE: Modifying the extensions/modules registered to the OHIF Viewer currently
> requires us to import and pass extensions to the ExtensionManager in
> `src/App.js`, then rebuild the application. Long-term, we intend to make it
> possible to accomplish this without a build step.
#### Commands
The Commands Module allows us to register one or more commands scoped to
specific contexts. Commands can be run by [hotkeys][#], [toolbar buttons][#],
and any registered custom react component (like a [viewport][#] or [panel][#]).
Here is a simple example commands module:
```js
{
getCommandsModule() {
return {
actions: {
speak: ({ viewports, words }) => {
console.log(viewports, words);
},
},
definitions: {
rotateViewportCW: {
commandFn: actions.rotateViewport,
storeContexts: ['viewports'],
options: { rotation: 90 }
},
rotateViewportCCW: {
commandFn: actions.rotateViewport,
storeContexts: ['viewports'],
options: { rotation: -90 },
context: 'ACTIVE_VIEWER::CORNERSTONE'
},
},
defaultContext: 'VIEWER'
}
}
}
```
#### Viewport
An extension can register a Viewport Module by providing a `getViewportModule()`
method that returns a React Component. The React component will receive the
following props:
```js
children: PropTypes.arrayOf(PropTypes.element)
studies: PropTypes.object,
displaySet: PropTypes.object,
viewportData: PropTypes.object, // { studies, displaySet }
viewportIndex: PropTypes.number,
children: PropTypes.node,
customProps: PropTypes.object
```
Viewport components are managed by the `ViewportGrid` Component. Which Viewport
component is used depends on:
- The Layout Configuration
- Registered SopClassHandlers
- The SopClassUID for visible/selected datasets
![Cornerstone Viewport](../assets/img/extensions-viewport.png)
<center><i>An example of three Viewports</i></center>
For a complete example implementation,
[check out the OHIFCornerstoneViewport](https://github.com/OHIF/Viewers/blob/master/extensions/cornerstone/src/OHIFCornerstoneViewport.js).
#### Toolbar
An extension can register a Toolbar Module by providing a `getToolbarModule()`
method that returns a React Component. The component does not receive any props.
If you want to modify or react to state, you will need to connect to the redux
store. The given toolbar must determine its set of elements and the context of
them. The set of elements will be listed on toolbar `definitions`.
![Toolbar Extension](../assets/img/extensions-toolbar.gif)
<center><i>A toolbar extension example</i></center>
Toolbar components are rendered in the `ToolbarRow` component.
For a complete example implementation,
[check out the OHIFCornerstoneViewport's Toolbar Module](https://github.com/OHIF/Viewers/blob/master/extensions/cornerstone/src/toolbarModule.js).
##### Toolbar Custom Component
Toolbar elements can define its own custom react component to be consumed when
rendering it. So far, it accepts `Functional` and `Class` Components. For that,
you just need to expose your `CustomToolbarComponent` as the value of key
`CustomComponent`. In case the property `CustomComponent` is not present, a
default toolbar component will be used to render it. See bellow
```js
definitions: [
...
{
id: 'Custom',
label: 'Custom',
icon: 'custom-icon',
CustomComponent: CustomToolbarComponent,
}
...
]
```
`CustomComponent` components will receive the following props:
- parentContext: parent context. (In most of the cases it will be a ToolbarRow
instance)
- toolbarClickCallback: callback method when clicking on toolbar
- button: its own definition object
- key: react key prop
- activeButtons: list of active elements
- isActive: if current
#### SopClassHandler
...
#### Panel
> The panel module is not yet in use.
#### Hotkeys
...
### Registering Extensions
Extensions are registered for the application at startup. The
`ExtensionManager`, exposed by `ohif-core`, registers a list of extensions with
our application's store. Each module provided by the extension becomes available
via `state.plugins.availablePlugins`, and consists of three parts: id, type
([PLUGIN_TYPE](https://github.com/OHIF/ohif-core/blob/43c08a29eff3fb646a0e83a03a236ddd84f4a6e8/src/plugins.js#L1-L6)),
and the return value of the module method.
In a future version, we will likely expose a way to provide the extensions you
would like included at startup.
_app.js_
```js
import { createStore, combineReducers } from 'redux';
import OHIF from '@ohif/core';
import OHIFCornerstoneExtension from 'ohif-cornerstone-extension';
const combined = combineReducers(OHIF.redux.reducers);
const store = createStore(combined);
const extensions = [new OHIFCornerstoneExtension()];
// Dispatches the `addPlugin` action to the store
// Adding extension modules to `state.plugins.availablePlugins`
ExtensionManager.registerExtensions(store, extensions);
```
## OHIF Maintained Extensions
A small number of powerful extensions for popular use cases are maintained by
OHIF. They're co-located in the
[`OHIF/Viewers`](https://github.com/OHIF/Viewers) repository, in the top level
[`extensions/`](https://github.com/OHIF/Viewers/tree/master/extensions)
directory.
{% include "./_maintained-extensions-table.md" %}
<!--
Links
-->
<!-- prettier-ignore-start -->
[example-ext-src]: https://github.com/OHIF/Viewers/tree/master/extensions/_example/src
[module-types]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/extensions/MODULE_TYPES.js
<!-- prettier-ignore-end -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -35,8 +35,7 @@ benefits, but comes at the cost of time and complexity. Some benefits include:
_Today:_
- Leverage [extensions](/advanced/extensions.md) to drop-in powerful new
features
- Leverage [extensions](/extensions/index.md) to drop-in powerful new features
- Add routes and customize the viewer's workflow
- Finer control over styling and whitelabeling

View File

@ -98,7 +98,7 @@ extension enabled here][whole-slide-ext-demo] ([source code][ext-code-sandbox])
and [without it here][whole-slide-base-demo] ([source code][code-sandbox]).
You can read more about extensions and how to create your own in our
[extensions guide](/advanced/extensions.md).
[extensions guide](/extensions/index.md).
#### FAQ

View File

@ -0,0 +1,62 @@
<table>
<thead>
<tr>
<th>Extension</th>
<th>Description</th>
<th>Modules</th>
</tr>
</thead>
<tbody>
<!-- CORNERSTONE.js -->
<tr>
<td>
<a href="https://www.npmjs.com/package/@ohif/extension-cornerstone">
Cornerstone
</a>
</td>
<td>
A viewport powered by <code>cornerstone.js</code>. Adds support for 2D DICOM rendering and manipulation, as well as support for the tools features in <a href="https://tools.cornerstonejs.org/examples/"><code>cornerstone-tools</code></a>. Also adds "CINE Dialog" to the Toolbar.
</td>
<td>Viewport, Toolbar</td>
</tr>
<!-- VTK.js -->
<tr>
<td>
<a href="https://www.npmjs.com/package/@ohif/extension-vtk">
VTK.js
</a>
</td>
<td>
A viewport powered by <code>vtk.js</code>. Adds support for volume renderings and advanced features like MPR. Also adds "3D Rotate" to the Toolbar.
</td>
<td>Viewport, Toolbar</td>
</tr>
<tr>
<td>
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-html">DICOM HTML</a>
</td>
<td>
Renders text and HTML content for <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-html/src/OHIFDicomHtmlSopClassHandler.js#L4-L12">specific SopClassUIDs</a>.
</td>
<td>Viewport, SopClassHandler</td>
</tr>
<tr>
<td>
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-pdf">DICOM PDF</a>
</td>
<td>
Renders PDFs for a <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-pdf/src/OHIFDicomPDFSopClassHandler.js#L4-L6">specific SopClassUID</a>.
</td>
<td>Viewport, SopClassHandler</td>
</tr>
<tr>
<td>
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-microscopy">DICOM Microscopy</a>
</td>
<td>
Renders Microscopy images for a <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-microscopy/src/DicomMicroscopySopClassHandler.js#L5-L7">specific SopClassUID</a>.
</td>
<td>Viewport, SopClassHandler</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,151 @@
# Extensions
- [Overview](#overview)
- [Concepts](#concepts)
- [Extension Skeleton](#extension-skeleton)
- [Registering an Extension](#registering-an-extension)
- [Lifecylce Hooks](#lifecycle-hooks)
- [Modules](#modules)
- [Contexts](#contexts)
- [Consuming Extensions](#consuming-extensions)
- [Maintained Extensions](#maintained-extensions)
## Overview
We use extensions to help us isolate and package groups of related features.
Extensions provide functionality, ui components, and new behaviors.
<div style="text-align: center;">
<a href="/assets/img/extensions-diagram.png">
<img src="/assets/img/extensions-diagram.png" alt="Extensions Diagram" style="margin: 0 auto; max-width: 500px;" />
</a>
<div><i>Diagram showing how extensions are configured and accessed.</i></div>
</div>
The `@ohif/viewer`'s application level configuration gives us the ability to add
and configure extensions. When the application starts, extensions are registered
with the `ExtensionManager`. Different portions of the `@ohif/viewer` project
will use registered extensions to influence application behavior.
Extensions allow us to:
- Wrap and integrate functionality of 3rd party dependencies in a reusable way
- Change how application data is mapped and transformed
- Display a consistent/cohesive UI
- Inject custom components to override built-in components
Practical examples of extensions include:
- A set of segmentation tools that build on top of the `cornerstone` viewport
- Showing ML/AI report summaries for the selected study/series/image
- Support for parsing DICOM structured reports and displaying them in a user
friendly way
- [See our maintained extensions for more examples of what's possible](#maintained-extensions)
## Concepts
### Extension Skeleton
An extension is a plain JavaScript object has an `id` property, and one or more
"getModuleFunctions" and/or lifecycle hooks. You can read more about
[lifecycle hooks](#lifecycle-hooks) and [modules](#modules) further down.
```js
// prettier-ignore
export default {
/**
* Only required property. Should be a unique value across all extensions.
*/
id: 'example-extension',
// Lifecyle
preRegistration() { /* */ },
// Modules
getCommandsModule() { /* */ },
getToolbarModule() { /* */ },
getPanelModule() { /* */ },
getSopClassHandler() { /* */ },
getViewportModule() { /* */ },
}
```
### Registering an Extension
There are two different ways to register and configure extensions. You can
leverage one or both strategies. Which one(s) you choose depend on your
application's requirements. Each [module](#modules) defined by the extension
becomes available to the core application via the `ExtensionManager`.
```js
// prettier-ignore
const config = {
extensions: [
MyFirstExtension,
[
MySecondExtension,
{ /* MySecondExtensions Configuration */ },
],
];
}
```
#### Runtime Extensions
The `@ohif/viewer` uses a [configuration file](#) at startup. The schema for
that file includes an `Extensions` key that supports an array of extensions to
register.
#### Bundled Extensions
The `@ohif/viewer` works best when built as a "Progressive Web Application"
(PWA). If you know the extensions your application will need, you can specify
them at "build time" to leverage some advantaged afforded to us by modern
tooling:
- Code Splitting
- Tree Shaking
- Dependency deduplication
You can update the list of bundled extensions by:
1. Having your `@ohif/viewer` project depend on the extension
2. Importing and adding it to the list of extensions in the
`<repo-root>/platform/src/index.js` entrypoint.
### Lifecycle Hooks
...
### Modules
There are a few different module types. Each module type allows us to extend the
viewer in a different way, and provides a consistent API for us to do so. You
can find a full list of the different types of modules
[`in ohif-core`][module-types]. Information on each type of module, it's API,
and how we determine when/where it should be used is included below.
### Contexts
...
## Consuming Extensions
...
## Maintained Extensions
A small number of powerful extensions for popular use cases are maintained by
OHIF. They're co-located in the [`OHIF/Viewers`][viewers-repo] repository, in
the top level [`extensions/`][ext-source] directory.
{% include "./_maintained-extensions-table.md" %}
<!--
LINKS
-->
<!-- prettier-ignore-start -->
[viewers-repo]: https://github.com/OHIF/Viewers
[ext-source]: https://github.com/OHIF/Viewers/tree/master/extensions
[module-types]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/extensions/MODULE_TYPES.js
<!-- prettier-ignore-end -->

View File

@ -0,0 +1,21 @@
# Lifecylce Hook: preRegistration
If an extension defines the `preRegistration` lifecycle hook, it is called
before any modules are registered to the `ExtensionManager`.
```js
export default {
id: 'MyExampleExtension',
preRegistration({ servicesManager, commandsManager, configuration }) {
console.log('Wiring up important stuff.');
window.importantStuff = () => {
console.log(configuration);
};
console.log('Important stuff has been wired.');
window.importantStuff();
},
};
```

View File

@ -0,0 +1,34 @@
# Module: Commands
The Commands Module allows us to register one or more commands scoped to
specific contexts. Commands can be run by [hotkeys][#], [toolbar buttons][#],
and any registered custom react component (like a [viewport][#] or [panel][#]).
Here is a simple example commands module:
```js
{
getCommandsModule() {
return {
actions: {
speak: ({ viewports, words }) => {
console.log(viewports, words);
},
},
definitions: {
rotateViewportCW: {
commandFn: actions.rotateViewport,
storeContexts: ['viewports'],
options: { rotation: 90 }
},
rotateViewportCCW: {
commandFn: actions.rotateViewport,
storeContexts: ['viewports'],
options: { rotation: -90 },
context: 'ACTIVE_VIEWER::CORNERSTONE'
},
},
defaultContext: 'VIEWER'
}
}
}
```

View File

@ -0,0 +1,3 @@
# Module: Panel
...

View File

@ -0,0 +1,3 @@
# Module: SOP Class Handler
...

View File

@ -0,0 +1,48 @@
# Module: Toolbar
An extension can register a Toolbar Module by providing a `getToolbarModule()`
method that returns a React Component. The component does not receive any props.
If you want to modify or react to state, you will need to connect to the redux
store. The given toolbar must determine its set of elements and the context of
them. The set of elements will be listed on toolbar `definitions`.
![Toolbar Extension](../assets/img/extensions-toolbar.gif)
<center><i>A toolbar extension example</i></center>
Toolbar components are rendered in the `ToolbarRow` component.
For a complete example implementation,
[check out the OHIFCornerstoneViewport's Toolbar Module](https://github.com/OHIF/Viewers/blob/master/extensions/cornerstone/src/toolbarModule.js).
## Toolbar Custom Component
Toolbar elements can define its own custom react component to be consumed when
rendering it. So far, it accepts `Functional` and `Class` Components. For that,
you just need to expose your `CustomToolbarComponent` as the value of key
`CustomComponent`. In case the property `CustomComponent` is not present, a
default toolbar component will be used to render it. See bellow
```js
definitions: [
...
{
id: 'Custom',
label: 'Custom',
icon: 'custom-icon',
CustomComponent: CustomToolbarComponent,
}
...
]
```
`CustomComponent` components will receive the following props:
- parentContext: parent context. (In most of the cases it will be a ToolbarRow
instance)
- toolbarClickCallback: callback method when clicking on toolbar
- button: its own definition object
- key: react key prop
- activeButtons: list of active elements
- isActive: if current

View File

@ -0,0 +1,29 @@
# Module: Viewport
An extension can register a Viewport Module by providing a `getViewportModule()`
method that returns a React Component. The React component will receive the
following props:
```js
children: PropTypes.arrayOf(PropTypes.element)
studies: PropTypes.object,
displaySet: PropTypes.object,
viewportData: PropTypes.object, // { studies, displaySet }
viewportIndex: PropTypes.number,
children: PropTypes.node,
customProps: PropTypes.object
```
Viewport components are managed by the `ViewportGrid` Component. Which Viewport
component is used depends on:
- The Layout Configuration
- Registered SopClassHandlers
- The SopClassUID for visible/selected datasets
![Cornerstone Viewport](../../assets/img/extensions-viewport.png)
<center><i>An example of three Viewports</i></center>
For a complete example implementation,
[check out the OHIFCornerstoneViewport](https://github.com/OHIF/Viewers/blob/master/extensions/cornerstone/src/OHIFCornerstoneViewport.js).

View File

@ -0,0 +1,3 @@
# Hotkeys
...

View File

@ -95,11 +95,11 @@ appropriate:
| [PR: Awaiting Review 👀][awaiting-review] | The core team has not yet performed a code review. |
| [PR: Awaiting Revisions 🖊][awaiting-revisions] | Following code review, this label is applied until the author has made sufficient changes. |
| **QA** | |
| [PR: Awaiting UX Stories 💃][awaiting-stories] | The PR code changes need common language descriptions of impact to end users before the review can start |
| [PR: Awaiting User Cases 💃][awaiting-stories] | The PR code changes need common language descriptions of impact to end users before the review can start |
| [PR: No UX Impact 🙃][no-ux-impact] | The PR code changes do not impact the user's experience |
We rely on GitHub Checks and integrations with third party services to evaluate
changes in code quality and test coverage. Tests must pass and UX stories must
changes in code quality and test coverage. Tests must pass and User cases must
be present (when applicable) before a PR can be merged to master, and code
quality and test coverage must not changed by a significant margin. For some
repositories, visual screenshot-based tests are also included, and video

View File

@ -33,7 +33,7 @@ The `ServicesManager` is:
- Passed to the `ExtensionManager`
- The `ExtensionManager` makes the `ServicesManager` available to:
- All of it's lifecycle hooks (`preInit`)
- All of it's lifecycle hooks (`preRegistration`)
- Each "getModuleFunction" (`getToolbarModule`, `getPanelModule`, etc.)
## Example

View File

@ -16,7 +16,7 @@
* @property {ReactElement|HTMLElement} content The dialog content.
* @property {Object} contentProps The dialog content props.
* @property {boolean} [isDraggable=true] Controls if dialog content is draggable or not.
* @property {boolean} [showOverlay=false] Controls dialog overlay.
* @property {boolean} [showOverlay=false] Controls dialog overlay.
* @property {ElementPosition} defaultPosition Specifies the `x` and `y` that the dragged item should start at.
* @property {ElementPosition} position If this property is present, the item becomes 'controlled' and is not responsive to user input.
* @property {Function} onStart Called when dragging starts. If `false` is returned any handler, the action will cancel.