import { action } from '@ember/object';
import { isBlank } from '@ember/utils';
import Component from '@glimmer/component';
import { next } from '@ember/runloop';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
import { ref } from 'ember-ref-bucket';
import { tracked } from '@glimmer/tracking';
import { guidFor } from '@ember/object/internals';
/**
Internal component for modal's markup and event handling. Should not be used directly.
@class ModalDialog
@namespace Components
@extends Glimmer.Component
@private
*/
@deprecateSubclassing
export default class ModalDialog extends Component {
/**
* @property id
* @type null | HTMLElement
*/
@ref('mainNode') _element = null;
/**
* Name of the size class
*
* @property sizeClass
* @type string
* @readOnly
* @private
*/
get sizeClass() {
let size = this.args.size;
return isBlank(size) ? null : `modal-${size}`;
}
/**
* The id of the `.modal-title` element
*
* @property titleId
* @type string
* @default null
* @private
*/
@tracked
titleId = null;
/**
* Gets or sets the id of the title element for aria accessibility tags
*
* @method getSetTitleID
* @private
*/
@action
getOrSetTitleId(modalNode) {
//Title element may be set by user so we have to try and find it to set the id
let nodeId = null;
if (modalNode) {
const titleNode = modalNode.querySelector('.modal-title');
if (titleNode) {
//Get title id of .modal-title
nodeId = titleNode.id;
if (!nodeId) {
//no title id so we set one
nodeId = `${guidFor(this)}-title`;
titleNode.id = nodeId;
}
}
}
this.titleId = nodeId;
}
@action
setInitialFocus(element) {
let autofocus = element && element.querySelector('[autofocus]');
if (autofocus) {
next(() => autofocus.focus());
}
}
/**
* If true clicking on the backdrop will be ignored and will not close modal.
*
* @property ignoreBackdropClick
* @type boolean
* @default false
* @private
*/
ignoreBackdropClick = false;
/**
* The target DOM element of mouse down event.
*
* @property mouseDownElement
* @type object
* @default null
* @private
*/
mouseDownElement = null;
/**
* @event onClose
* @public
*/
@action
handleKeyDown(e) {
let code = e.keyCode || e.which;
if (code === 27 && this.args.keyboard) {
this.args.onClose?.();
}
}
@action
handleClick(e) {
if (this.ignoreBackdropClick) {
this.ignoreBackdropClick = false;
return;
}
if (e.target !== this._element || !this.args.backdropClose) {
return;
}
this.args.onClose?.();
}
@action
handleMouseDown(e) {
this.mouseDownElement = e.target;
}
@action
handleMouseUp(e) {
if (this.mouseDownElement !== this._element && e.target === this._element) {
this.ignoreBackdropClick = true;
}
}
}