diff --git a/addon/components/modal-dialog.js b/addon/components/modal-dialog.js
deleted file mode 100644
index 7d0ef80d..00000000
--- a/addon/components/modal-dialog.js
+++ /dev/null
@@ -1,157 +0,0 @@
-import { tagName, layout as templateLayout } from '@ember-decorators/component';
-import { action, computed, set } from '@ember/object';
-import { inject as service } from '@ember/service';
-import { readOnly, oneWay } from '@ember/object/computed';
-import Component from '@ember/component';
-import { dasherize } from '@ember/string';
-import { isEmpty, typeOf, isNone } from '@ember/utils';
-import layout from '../templates/components/modal-dialog';
-import { assert, warn } from '@ember/debug';
-import { DEBUG } from '@glimmer/env';
-import { importSync } from '@embroider/macros';
-import { ensureSafeComponent } from '@embroider/util';
-
-const VALID_OVERLAY_POSITIONS = ['parent', 'sibling'];
-
-@tagName('')
-@templateLayout(layout)
-export default class ModalDialog extends Component {
- @service('modal-dialog')
- modalService;
-
- animatable = null;
- clickOutsideToClose = false;
- destinationElementId = null;
- hasOverlay = true;
- overlayPosition = 'parent'; // `parent` or `sibling`
- renderInPlace = false;
- targetAttachment = 'middle center';
- tetherClassPrefix = null;
- tetherTarget = null;
- translucentOverlay = false;
- value = 0; // pass a `value` to set a "value" to be passed to liquid-wormhole / liquid-tether
-
- @readOnly('modalService.hasLiquidWormhole')
- hasLiquidWormhole;
-
- @readOnly('modalService.hasLiquidTether')
- hasLiquidTether;
-
- @oneWay('elementId')
- stack; // pass a `stack` string to set a "stack" to be passed to liquid-wormhole / liquid-tether
-
- @computed('attachment')
- get attachmentClass() {
- let attachment = this.attachment;
- if (isEmpty(attachment)) {
- return undefined;
- }
- return attachment
- .split(' ')
- .map((attachmentPart) => {
- return `emd-attachment-${dasherize(attachmentPart)}`;
- })
- .join(' ');
- }
-
- @computed(
- 'renderInPlace',
- 'tetherTarget',
- 'animatable',
- 'hasLiquidWormhole',
- 'hasLiquidTether'
- )
- get whichModalDialogComponent() {
- let { animatable, hasLiquidTether, hasLiquidWormhole, tetherTarget } = this;
- let module = importSync('ember-modal-dialog/components/basic-dialog');
-
- if (this.renderInPlace) {
- module = importSync('ember-modal-dialog/components/in-place-dialog');
- } else if (
- tetherTarget &&
- hasLiquidTether &&
- hasLiquidWormhole &&
- animatable === true
- ) {
- module = importSync('ember-modal-dialog/components/liquid-tether-dialog');
- } else if (tetherTarget) {
- this.ensureEmberTetherPresent();
- module = importSync('ember-modal-dialog/components/tether-dialog');
- } else if (hasLiquidWormhole && animatable === true) {
- module = importSync('ember-modal-dialog/components/liquid-dialog');
- }
-
- return ensureSafeComponent(module.default, this);
- }
-
- init() {
- super.init(...arguments);
-
- if (!this.destinationElementId) {
- set(this, 'destinationElementId', this.modalService.destinationElementId);
- }
- }
-
- didReceiveAttrs() {
- super.didReceiveAttrs(...arguments);
- if (DEBUG) {
- this.validateProps();
- }
- }
-
- validateProps() {
- let overlayPosition = this.overlayPosition;
- if (VALID_OVERLAY_POSITIONS.indexOf(overlayPosition) === -1) {
- warn(
- `overlayPosition value '${overlayPosition}' is not valid (valid values [${VALID_OVERLAY_POSITIONS.join(
- ', '
- )}])`,
- false,
- { id: 'ember-modal-dialog.validate-overlay-position' }
- );
- }
- }
-
- ensureEmberTetherPresent() {
- if (!this.modalService.hasEmberTether) {
- throw new Error(
- 'Please install ember-tether in order to pass a tetherTarget to modal-dialog'
- );
- }
- }
-
- @action
- onCloseAction() {
- const onClose = this.onClose;
- // we shouldn't warn if the callback is not provided at all
- if (isNone(onClose)) {
- return;
- }
-
- assert(
- 'onClose handler must be a function',
- typeOf(onClose) === 'function'
- );
-
- onClose();
- }
-
- @action
- onClickOverlayAction(e) {
- e.preventDefault();
-
- const onClickOverlay = this.onClickOverlay;
- // we shouldn't warn if the callback is not provided at all
- if (isNone(onClickOverlay)) {
- this.onCloseAction();
- return;
- }
-
- assert(
- 'onClickOverlay handler must be a function',
- typeOf(onClickOverlay) === 'function'
- );
-
- onClickOverlay();
- }
-}
diff --git a/addon/components/modal-dialog/index.hbs b/addon/components/modal-dialog/index.hbs
new file mode 100644
index 00000000..5dc98f08
--- /dev/null
+++ b/addon/components/modal-dialog/index.hbs
@@ -0,0 +1,31 @@
+
+ {{yield}}
+
\ No newline at end of file
diff --git a/addon/components/modal-dialog/index.js b/addon/components/modal-dialog/index.js
new file mode 100644
index 00000000..85532133
--- /dev/null
+++ b/addon/components/modal-dialog/index.js
@@ -0,0 +1,180 @@
+import Component from '@glimmer/component';
+import { inject as service } from '@ember/service';
+import { dasherize } from '@ember/string';
+import { typeOf } from '@ember/utils';
+import { assert, warn } from '@ember/debug';
+import { DEBUG } from '@glimmer/env';
+import { importSync } from '@embroider/macros';
+import { ensureSafeComponent } from '@embroider/util';
+import { guidFor } from '@ember/object/internals';
+
+const VALID_OVERLAY_POSITIONS = ['parent', 'sibling'];
+
+// Args:
+// `hasOverlay` | Toggles presence of overlay div in DOM
+// `translucentOverlay` | Indicates translucence of overlay, toggles presence of `translucent` CSS selector
+// `onClose` | The action handler for the dialog's `onClose` action. This action triggers when the user clicks the modal overlay.
+// `onClickOverlay` | An action to be called when the overlay is clicked. If this action is specified, clicking the overlay will invoke it instead of `onClose`.
+// `clickOutsideToClose` | Indicates whether clicking outside a modal *without* an overlay should close the modal. Useful if your modal isn't the focus of interaction, and you want hover effects to still work outside the modal.
+// `renderInPlace` | A boolean, when true renders the modal without wormholing or tethering, useful for including a modal in a style guide
+// `overlayPosition` | either `'parent'` or `'sibling'`, to control whether the overlay div is rendered as a parent element of the container div or as a sibling to it (default: `'parent'`)
+// `containerClass` | CSS class name(s) to append to container divs. Set this from template.
+// `containerClassNames` | CSS class names to append to container divs. If you subclass this component, you may define this in your subclass.)
+// `overlayClass` | CSS class name(s) to append to overlay divs. Set this from template.
+// `overlayClassNames` | CSS class names to append to overlay divs. If you subclass this component, you may define this in your subclass.)
+// `wrapperClass` | CSS class name(s) to append to wrapper divs. Set this from template.
+// `wrapperClassNames` | CSS class names to append to wrapper divs. If you subclass this component, you may define this in your subclass.)
+// `animatable` | A boolean, when `true` makes modal animatable using `liquid-fire` (requires `liquid-wormhole` to be installed, and for tethering situations `liquid-tether`. Having these optional dependencies installed and not specifying `animatable` will make `animatable=true` be the default.)
+// `tetherTarget` | If you specify a `tetherTarget`, you are opting into "tethering" behavior, and you must have either `ember-tether` or `liquid-tether` installed.
+// `destinationElementId`| optional
+// `targetAttachment` | Delegates to Hubspot Tether*
+// `tetherClassPrefix` | Delegates to Hubspot Tether*
+// `offset` | Delegates to Hubspot Tether*
+// `targetOffset` | Delegates to Hubspot Tether*
+// `constraints` | Delegates to Hubspot Tether*
+// `stack` | Delegates to liquid-wormhole/liquid-tether
+// `value` | pass a `value` to set a "value" to be passed to liquid-wormhole / liquid-tether
+
+export default class ModalDialog extends Component {
+ @service('modal-dialog') modalService;
+
+ get value() {
+ // pass a `value` to set a "value" to be passed to liquid-wormhole / liquid-tether
+ return this.args.value || 0;
+ }
+ get hasLiquidWormhole() {
+ return this.modalService.hasLiquidWormhole;
+ }
+
+ get hasLiquidTether() {
+ return this.modalService.hasLiquidTether;
+ }
+
+ get hasOverlay() {
+ return this.args.hasOverlay ?? true;
+ }
+
+ get stack() {
+ // this `stack` string will be set as this element's ID and passed to liquid-wormhole / liquid-tether
+ return guidFor(this);
+ }
+
+ get containerClassNamesVal() {
+ return this.args.containerClassNames || this.containerClassNames || null;
+ }
+
+ get attachmentClass() {
+ let { attachment } = this.args;
+ if (!attachment) {
+ return undefined;
+ }
+ return attachment
+ .split(' ')
+ .map((attachmentPart) => {
+ return `emd-attachment-${dasherize(attachmentPart)}`;
+ })
+ .join(' ');
+ }
+
+ get targetAttachment() {
+ return this.args.targetAttachment || 'middle center';
+ }
+
+ get whichModalDialogComponent() {
+ let { hasLiquidTether, hasLiquidWormhole } = this;
+ let { animatable, tetherTarget, renderInPlace } = this.args;
+ let module = importSync('ember-modal-dialog/components/basic-dialog');
+
+ if (renderInPlace) {
+ module = importSync('ember-modal-dialog/components/in-place-dialog');
+ } else if (
+ tetherTarget &&
+ hasLiquidTether &&
+ hasLiquidWormhole &&
+ animatable === true
+ ) {
+ module = importSync('ember-modal-dialog/components/liquid-tether-dialog');
+ } else if (tetherTarget) {
+ this.ensureEmberTetherPresent();
+ module = importSync('ember-modal-dialog/components/tether-dialog');
+ } else if (hasLiquidWormhole && animatable === true) {
+ module = importSync('ember-modal-dialog/components/liquid-dialog');
+ }
+
+ return ensureSafeComponent(module.default, this);
+ }
+
+ get destinationElementId() {
+ return (
+ this.args.destinationElementId || this.modalService.destinationElementId
+ );
+ }
+
+ validateProps() {
+ let overlayPosition = this.overlayPosition;
+ if (VALID_OVERLAY_POSITIONS.indexOf(overlayPosition) === -1) {
+ warn(
+ `overlayPosition value '${overlayPosition}' is not valid (valid values [${VALID_OVERLAY_POSITIONS.join(
+ ', '
+ )}])`,
+ false,
+ { id: 'ember-modal-dialog.validate-overlay-position' }
+ );
+ }
+ }
+
+ get overlayPosition() {
+ let result = this.args.overlayPosition || 'parent';
+ if (DEBUG && VALID_OVERLAY_POSITIONS.indexOf(result) === -1) {
+ warn(
+ `overlayPosition value '${result}' is not valid (valid values [${VALID_OVERLAY_POSITIONS.join(
+ ', '
+ )}])`,
+ false,
+ { id: 'ember-modal-dialog.validate-overlay-position' }
+ );
+ }
+ return result;
+ }
+
+ ensureEmberTetherPresent() {
+ if (!this.modalService.hasEmberTether) {
+ throw new Error(
+ 'Please install ember-tether in order to pass a tetherTarget to modal-dialog'
+ );
+ }
+ }
+
+ onCloseAction = () => {
+ const { onClose } = this.args;
+ // we shouldn't warn if the callback is not provided at all
+ if (!onClose) {
+ return;
+ }
+
+ assert(
+ 'onClose handler must be a function',
+ typeOf(onClose) === 'function'
+ );
+
+ onClose();
+ };
+
+ onClickOverlayAction = (ev) => {
+ ev.preventDefault();
+
+ const { onClickOverlay } = this.args;
+ // we shouldn't warn if the callback is not provided at all
+ if (!onClickOverlay) {
+ this.onCloseAction();
+ return;
+ }
+
+ assert(
+ 'onClickOverlay handler must be a function',
+ typeOf(onClickOverlay) === 'function'
+ );
+
+ onClickOverlay();
+ };
+}
diff --git a/addon/templates/components/modal-dialog.hbs b/addon/templates/components/modal-dialog.hbs
deleted file mode 100644
index 274a895c..00000000
--- a/addon/templates/components/modal-dialog.hbs
+++ /dev/null
@@ -1,30 +0,0 @@
-
- {{yield}}
-
\ No newline at end of file