import { tagName } from '@ember-decorators/component';
import { computed } from '@ember/object';
import { addObserver } from '@ember/object/observers';
import Component from '@ember/component';
import { scheduleOnce } from '@ember/runloop';
import ComponentChild from 'ember-bootstrap/mixins/component-child';
import transitionEnd from 'ember-bootstrap/utils/transition-end';
import usesTransition from 'ember-bootstrap/utils/cp/uses-transition';
import defaultValue from 'ember-bootstrap/utils/default-decorator';
import { guidFor } from '@ember/object/internals';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
import { ref } from 'ember-ref-bucket';
/**
The tab pane of a tab component.
See [Components.Tab](Components.Tab.html) for examples.
@class TabPane
@namespace Components
@extends Ember.Component
@uses Mixins.ComponentChild
@public
*/
@tagName('')
@deprecateSubclassing
export default class TabPane extends Component.extend(ComponentChild) {
/**
* @property id
* @type null | HTMLElement
*/
@ref('mainNode') _element = null;
/**
* @property id
* @type string
* @public
*/
id = guidFor(this);
/**
* @property activeId
* @private
*/
@defaultValue
activeId = null;
/**
* True if this pane is active (visible)
*
* @property isActive
* @type boolean
* @readonly
* @private
*/
@(computed('activeId', 'id').readOnly())
get isActive() {
return this.activeId === this.id;
}
/**
* Used to apply Bootstrap's "active" class
*
* @property active
* @type boolean
* @default false
* @private
*/
@defaultValue
active = false;
/**
* Used to trigger the Bootstrap visibility classes.
*
* @property showContent
* @type boolean
* @default false
* @private
*/
@defaultValue
showContent = false;
/**
* The title for this tab pane. This is used by the `bs-tab` component to automatically generate
* the tab navigation.
* See the [Components.Tab](Components.Tab.html) for examples.
*
* @property title
* @type string
* @default null
* @public
*/
@defaultValue
title = null;
/**
* An optional group title used by the `bs-tab` component to group all panes with the same group title
* under a common drop down in the tab navigation.
* See the [Components.Tab](Components.Tab.html) for examples.
*
* @property groupTitle
* @type string
* @default null
* @public
*/
@defaultValue
groupTitle = null;
/**
* Use fade animation when switching tabs.
*
* @property fade
* @type boolean
* @private
*/
@defaultValue
fade = true;
/**
* The duration of the fade out animation
*
* @property fadeDuration
* @type integer
* @default 150
* @private
*/
@defaultValue
fadeDuration = 150;
/**
* Use CSS transitions?
*
* @property usesTransition
* @type boolean
* @readonly
* @private
*/
@usesTransition('fade')
usesTransition;
/**
* Show the pane
*
* @method show
* @protected
*/
show() {
if (this.usesTransition) {
if (!this._element) {
// _element is initially set by `{{create-ref}}` which happens in next run loop, so can be undefined here.
this.setProperties({
active: true,
showContent: true,
});
} else {
transitionEnd(this._element, this.fadeDuration).then(() => {
if (!this.isDestroyed) {
this.setProperties({
active: true,
showContent: true,
});
}
});
}
} else {
this.set('active', true);
}
}
/**
* Hide the pane
*
* @method hide
* @protected
*/
hide() {
if (this.usesTransition) {
transitionEnd(this._element, this.fadeDuration).then(() => {
if (!this.isDestroyed) {
this.set('active', false);
}
});
this.set('showContent', false);
} else {
this.set('active', false);
}
}
_showHide() {
if (this.isActive) {
this.show();
} else {
this.hide();
}
}
_setActive() {
this.set('active', this.isActive);
this.set('showContent', this.isActive && this.fade);
}
init() {
super.init(...arguments);
// isActive comes from parent component, so only available after render...
scheduleOnce('afterRender', this, this._setActive);
addObserver(this, 'isActive', null, this._showHide, true);
}
}