'use strict';

Liferay.Loader.define("frontend-taglib-clay$clay-modal@2.24.1/lib/ClayModal", ['module', 'exports', 'require', 'frontend-taglib-clay$clay-button', 'frontend-taglib-clay$clay-icon', 'frontend-js-metal-web$metal-state', 'frontend-js-metal-web$metal-events', 'frontend-taglib-clay$clay-component', 'frontend-js-metal-web$metal-web-component', 'frontend-js-metal-web$metal-dom', 'frontend-js-metal-web$metal-soy', './ClayModal.soy'], function (module, exports, require) {
	var define = undefined;
	var global = window;
	{
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		exports.ClayModal = undefined;

		var _createClass = function () {
			function defineProperties(target, props) {
				for (var i = 0; i < props.length; i++) {
					var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
				}
			}return function (Constructor, protoProps, staticProps) {
				if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
			};
		}();

		var _get = function get(object, property, receiver) {
			if (object === null) object = Function.prototype;var desc = Object.getOwnPropertyDescriptor(object, property);if (desc === undefined) {
				var parent = Object.getPrototypeOf(object);if (parent === null) {
					return undefined;
				} else {
					return get(parent, property, receiver);
				}
			} else if ("value" in desc) {
				return desc.value;
			} else {
				var getter = desc.get;if (getter === undefined) {
					return undefined;
				}return getter.call(receiver);
			}
		};

		require("frontend-taglib-clay$clay-button");

		require("frontend-taglib-clay$clay-icon");

		var _metalState = require("frontend-js-metal-web$metal-state");

		var _metalEvents = require("frontend-js-metal-web$metal-events");

		var _clayComponent = require("frontend-taglib-clay$clay-component");

		var _clayComponent2 = _interopRequireDefault(_clayComponent);

		var _metalWebComponent = require("frontend-js-metal-web$metal-web-component");

		var _metalWebComponent2 = _interopRequireDefault(_metalWebComponent);

		var _metalDom = require("frontend-js-metal-web$metal-dom");

		var _metalDom2 = _interopRequireDefault(_metalDom);

		var _metalSoy = require("frontend-js-metal-web$metal-soy");

		var _metalSoy2 = _interopRequireDefault(_metalSoy);

		var _ClayModalSoy = require("./ClayModal.soy");

		var _ClayModalSoy2 = _interopRequireDefault(_ClayModalSoy);

		function _interopRequireDefault(obj) {
			return obj && obj.__esModule ? obj : { default: obj };
		}

		function _classCallCheck(instance, Constructor) {
			if (!(instance instanceof Constructor)) {
				throw new TypeError("Cannot call a class as a function");
			}
		}

		function _possibleConstructorReturn(self, call) {
			if (!self) {
				throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
			}return call && (typeof call === "object" || typeof call === "function") ? call : self;
		}

		function _inherits(subClass, superClass) {
			if (typeof superClass !== "function" && superClass !== null) {
				throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
			}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
		}

		var KEY_CODE_ESC = 27;
		var KEY_CODE_TAB = 9;

		var FOCUSABLE_ELEMENTS = ['a[href]', '[contenteditable]', '[tabindex]:not([tabindex^="-"])', 'area[href]', 'button:not([disabled]):not([aria-hidden])', 'embed', 'iframe', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'object', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])'];

		var counter = 0;

		/**
   * Metal ClayModal component.
   * @extends ClayComponent
   */

		var ClayModal = function (_ClayComponent) {
			_inherits(ClayModal, _ClayComponent);

			function ClayModal() {
				_classCallCheck(this, ClayModal);

				return _possibleConstructorReturn(this, (ClayModal.__proto__ || Object.getPrototypeOf(ClayModal)).apply(this, arguments));
			}

			_createClass(ClayModal, [{
				key: 'created',

				/**
     * @inheritDoc
     */
				value: function created() {
					this._overlayElement = this._valueOverlayElementFn();
					this._eventHandler = new _metalEvents.EventHandler();
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'attached',
				value: function attached() {
					this.addListener('click', this._handleDocumentClick.bind(this), true);
					this.addListener('hide', this._defaultHideModal, true);
					this.addListener('show', this._defaultShowModal, true);
					this.addListener('touchend', this._handleDocumentClick.bind(this), true);
					this.addListener('transitionend', this._handleTransitionEnd, true);
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'detached',
				value: function detached() {
					_get(ClayModal.prototype.__proto__ || Object.getPrototypeOf(ClayModal.prototype), 'detached', this).call(this);
					this._eventHandler.removeAllListeners();
				}

				/**
     * @inheritDoc
     */
				// eslint-disable-next-line

			}, {
				key: 'sync_isTransitioning',
				value: function sync_isTransitioning() {
					if (this._isTransitioning && !this.visible) {
						this._isTransitioning = false;
						this.visible = true;
					} else if (this._isTransitioning && this.visible) {
						this.visible = false;
					}
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'syncVisible',
				value: function syncVisible() {
					if (this.visible) {
						_metalDom2.default.enterDocument(this._overlayElement);
						this._overlayElement.offsetHeight;
						_metalDom2.default.addClasses(this._overlayElement, 'show');
						this.element.focus();
					} else {
						_metalDom2.default.exitDocument(this._overlayElement);
					}
				}

				/**
     * Close modal and remove transitions.
     * @private
     */

			}, {
				key: '_defaultHideModal',
				value: function _defaultHideModal() {
					_metalDom2.default.removeClasses(this._overlayElement, 'show');
					_metalDom2.default.removeClasses(document.body, 'modal-open');

					this._isTransitioning = true;

					this._eventHandler.removeAllListeners();
				}

				/**
     * Open modal and add transition.
     * @private
     */

			}, {
				key: '_defaultShowModal',
				value: function _defaultShowModal() {
					_metalDom2.default.addClasses(document.body, 'modal-open');

					this._isTransitioning = true;

					this._eventHandler.add(_metalDom2.default.on(document, 'keyup', this._handleKeyup.bind(this)), _metalDom2.default.on(document, 'keydown', this._handleKeyDown.bind(this)));
				}

				/**
     * Get all nodes that can be focused.
     * @protected
     * @return {!Array}
     */

			}, {
				key: '_getFocusableNodes',
				value: function _getFocusableNodes() {
					var nodes = this.element.querySelectorAll(FOCUSABLE_ELEMENTS);
					return Object.keys(nodes).map(function (key) {
						return nodes[key];
					});
				}

				/**
     * Handles the focus on the elements within the modal.
     * @param {!Event} event
     * @protected
     */

			}, {
				key: '_handleKeyDown',
				value: function _handleKeyDown(event) {
					if (event.keyCode === KEY_CODE_TAB) {
						if (!this.element.contains(event.target)) {
							this.element.focus();
						} else {
							var focusableNodes = this._getFocusableNodes();
							var focusedItemIndex = focusableNodes.indexOf(document.activeElement);

							if (event.shiftKey && focusedItemIndex === 0) {
								focusableNodes[focusableNodes.length - 1].focus();
								event.preventDefault();
							}

							if (!event.shiftKey && focusedItemIndex === focusableNodes.length - 1) {
								focusableNodes[0].focus();
								event.preventDefault();
							}
						}
					}
				}

				/**
     * Handle the click buttons and emit event.
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleClickFooterButton',
				value: function _handleClickFooterButton(event) {
					this.emit('clickButton', event);
				}

				/**
     * Handle the footer close button click and emits events.
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleClickCloseButtonFooter',
				value: function _handleClickCloseButtonFooter(event) {
					this.emit('clickButton', event);
					this.emit('hide');
				}

				/**
     * Handle the click and emit close modal.
     * @private
     */

			}, {
				key: '_handleCloseModal',
				value: function _handleCloseModal() {
					this.emit('hide');
				}

				/**
     * Check if contain click target event in element and emit close modal.
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleDocumentClick',
				value: function _handleDocumentClick(event) {
					if (_metalDom2.default.contains(event.target, this.element)) {
						this.emit('hide');
					}
				}

				/**
     * Handle click key code esc and emit close modal.
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleKeyup',
				value: function _handleKeyup(event) {
					if (event.keyCode === KEY_CODE_ESC) {
						this.emit('hide');
					}
				}

				/**
     * Handle css transition ends.
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleTransitionEnd',
				value: function _handleTransitionEnd(event) {
					if (event.target === this.element && this._isTransitioning && !this.visible) {
						this._isTransitioning = false;
					}
				}

				/**
     * Create fragment of the overlay modal.
     * @return {Element} The resulting document fragment.
     * @private
     */

			}, {
				key: '_valueOverlayElementFn',
				value: function _valueOverlayElementFn() {
					return _metalDom2.default.buildFragment('<div class="modal-backdrop fade"></div>').firstChild;
				}

				/**
     * Emit open modal.
     * @public
     */

			}, {
				key: 'show',
				value: function show() {
					this.emit('show');
				}
			}]);

			return ClayModal;
		}(_clayComponent2.default);

		/**
   * State definition.
   * @static
   * @type {!Object}
   */

		ClayModal.STATE = {
			/**
    * The attribute identifies the title that labels the Modal.
    * @instance
    * @memberof ClayModal
    * @type {string}
    */
			ariaLabelledby: _metalState.Config.setter(function (value) {
				counter++;

				return value ? value : 'clayv2-modal-label-' + counter;
			}),

			/**
    * Body of the modal.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|html|undefined)}
    */
			body: _metalState.Config.any(),

			/**
    * Data to add to the element.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?object}
    */
			data: _metalState.Config.object(),

			/**
    * Object that wires events with default listeners
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @review
    * @type {?(object|undefined)}
    */
			defaultEventHandler: _metalState.Config.object(),

			/**
    * CSS classes to be applied to the element.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			elementClasses: _metalState.Config.string(),

			/**
    * Buttons of the footer.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(array|undefined)}
    */
			footerButtons: _metalState.Config.arrayOf(_metalState.Config.shapeOf({
				alignment: _metalState.Config.oneOf(['left', 'right']).value('right'),
				label: _metalState.Config.string().required(),
				style: _metalState.Config.oneOf(['link', 'primary', 'secondary', 'unstyled']),
				type: _metalState.Config.oneOf(['button', 'close', 'reset', 'submit']).value('button')
			})),

			/**
    * Id to be applied to the element.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			id: _metalState.Config.string(),

			/**
    * Adds transitions when show is called.
    * @default false
    * @instance
    * @memberof ClayModal
    * @private
    * @type {?bool}
    */
			_isTransitioning: _metalState.Config.bool().value(false).internal(),

			/**
    * The size of element modal.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			size: _metalState.Config.oneOf(['full-screen', 'lg', 'sm']),

			/**
    * The path to the SVG spritemap file containing the icons.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			spritemap: _metalState.Config.string(),

			/**
    * Status messages.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			status: _metalState.Config.oneOf(['danger', 'info', 'success', 'warning']),

			/**
    * Title of the modal.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			title: _metalState.Config.string(),

			/**
    * Url to place an iframe in the body of the modal.
    * @default undefined
    * @instance
    * @memberof ClayModal
    * @type {?(string|undefined)}
    */
			url: _metalState.Config.string(),

			/**
    * Modal visible when show is called.
    * @default false
    * @instance
    * @memberof ClayModal
    * @private
    * @type {?bool}
    */
			visible: _metalState.Config.bool().value(false)
		};

		(0, _metalWebComponent2.default)('clay-modal', ClayModal);

		_metalSoy2.default.register(ClayModal, _ClayModalSoy2.default);

		exports.ClayModal = ClayModal;
		exports.default = ClayModal;
		//# sourceMappingURL=ClayModal.js.map
	}
});
//# sourceMappingURL=ClayModal.js.map