bootstrap-vue
Version:
With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extens
135 lines (127 loc) • 4.09 kB
JavaScript
import { PortalTarget, Wormhole } from 'portal-vue';
import { extend } from '../../vue';
import { NAME_TOASTER } from '../../constants/components';
import { EVENT_NAME_DESTROYED } from '../../constants/events';
import { PROP_TYPE_STRING } from '../../constants/props';
import { removeClass, requestAF } from '../../utils/dom';
import { getRootEventName } from '../../utils/events';
import { makeProp, makePropsConfigurable } from '../../utils/props';
import { warn } from '../../utils/warn';
import { listenOnRootMixin } from '../../mixins/listen-on-root';
import { normalizeSlotMixin } from '../../mixins/normalize-slot'; // --- Helper components ---
// @vue/component
export var DefaultTransition = /*#__PURE__*/extend({
mixins: [normalizeSlotMixin],
data: function data() {
return {
// Transition classes base name
name: 'b-toaster'
};
},
methods: {
onAfterEnter: function onAfterEnter(el) {
var _this = this;
// Work around a Vue.js bug where `*-enter-to` class is not removed
// See: https://github.com/vuejs/vue/pull/7901
// The `*-move` class is also stuck on elements that moved,
// but there are no JavaScript hooks to handle after move
// See: https://github.com/vuejs/vue/pull/7906
requestAF(function () {
removeClass(el, "".concat(_this.name, "-enter-to"));
});
}
},
render: function render(h) {
return h('transition-group', {
props: {
tag: 'div',
name: this.name
},
on: {
afterEnter: this.onAfterEnter
}
}, this.normalizeSlot());
}
}); // --- Props ---
export var props = makePropsConfigurable({
// Allowed: 'true' or 'false' or `null`
ariaAtomic: makeProp(PROP_TYPE_STRING),
ariaLive: makeProp(PROP_TYPE_STRING),
name: makeProp(PROP_TYPE_STRING, undefined, true),
// Required
// Aria role
role: makeProp(PROP_TYPE_STRING)
}, NAME_TOASTER); // --- Main component ---
// @vue/component
export var BToaster = /*#__PURE__*/extend({
name: NAME_TOASTER,
mixins: [listenOnRootMixin],
props: props,
data: function data() {
return {
// We don't render on SSR or if a an existing target found
doRender: false,
dead: false,
// Toaster names cannot change once created
staticName: this.name
};
},
beforeMount: function beforeMount() {
var name = this.name;
this.staticName = name;
/* istanbul ignore if */
if (Wormhole.hasTarget(name)) {
warn("A \"<portal-target>\" with name \"".concat(name, "\" already exists in the document."), NAME_TOASTER);
this.dead = true;
} else {
this.doRender = true;
}
},
beforeDestroy: function beforeDestroy() {
// Let toasts made with `this.$bvToast.toast()` know that this toaster
// is being destroyed and should should also destroy/hide themselves
if (this.doRender) {
this.emitOnRoot(getRootEventName(NAME_TOASTER, EVENT_NAME_DESTROYED), this.name);
}
},
destroyed: function destroyed() {
// Remove from DOM if needed
var $el = this.$el;
/* istanbul ignore next: difficult to test */
if ($el && $el.parentNode) {
$el.parentNode.removeChild($el);
}
},
render: function render(h) {
var $toaster = h('div', {
class: ['d-none', {
'b-dead-toaster': this.dead
}]
});
if (this.doRender) {
var $target = h(PortalTarget, {
staticClass: 'b-toaster-slot',
props: {
name: this.staticName,
multiple: true,
tag: 'div',
slim: false,
// transition: this.transition || DefaultTransition
transition: DefaultTransition
}
});
$toaster = h('div', {
staticClass: 'b-toaster',
class: [this.staticName],
attrs: {
id: this.staticName,
// Fallback to null to make sure attribute doesn't exist
role: this.role || null,
'aria-live': this.ariaLive,
'aria-atomic': this.ariaAtomic
}
}, [$target]);
}
return $toaster;
}
});