(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.bootstrapVue = factory()); }(this, (function () { 'use strict'; var __assign = Object.assign || function (e) { for (var a, s = 1, t = arguments.length; s < t; s++) { for (var r in a = arguments[s]) { Object.prototype.hasOwnProperty.call(a, r) && (e[r] = a[r]); } }return e; };function mergeData() { for (var e, a, s = {}, t = arguments.length; t--;) { for (var r = 0, c = Object.keys(arguments[t]); r < c.length; r++) { switch (e = c[r]) {case "class":case "style":case "directives": Array.isArray(s[e]) || (s[e] = []), s[e] = s[e].concat(arguments[t][e]);break;case "staticClass": if (!arguments[t][e]) break;void 0 === s[e] && (s[e] = ""), s[e] && (s[e] += " "), s[e] += arguments[t][e].trim();break;case "on":case "nativeOn": s[e] || (s[e] = {});for (var o = 0, n = Object.keys(arguments[t][e] || {}); o < n.length; o++) { a = n[o], s[e][a] ? s[e][a] = [].concat(s[e][a], arguments[t][e][a]) : s[e][a] = arguments[t][e][a]; }break;case "attrs":case "props":case "domProps":case "scopedSlots":case "staticStyle":case "hook":case "transition": s[e] || (s[e] = {}), s[e] = __assign({}, arguments[t][e], s[e]);break;case "slot":case "key":case "ref":case "tag":case "show":case "keepAlive":default: s[e] || (s[e] = arguments[t][e]);} } }return s; } var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; 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 defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var inherits = function (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 possibleConstructorReturn = function (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; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; var props = { disabled: { type: Boolean, default: false }, ariaLabel: { type: String, default: 'Close' }, textVariant: { type: String, default: null } }; var bBtnClose = { functional: true, props: props, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, listeners = _ref.listeners, slots = _ref.slots; var componentData = { staticClass: 'close', class: defineProperty({}, 'text-' + props.textVariant, props.textVariant), attrs: { type: 'button', disabled: props.disabled, 'aria-label': props.ariaLabel ? String(props.ariaLabel) : null }, on: { click: function click(e) { // Ensure click on button HTML content is also disabled if (props.disabled && e instanceof Event) { e.stopPropagation(); e.preventDefault(); } } } // Careful not to override the slot with innerHTML };if (!slots().default) { componentData.domProps = { innerHTML: '×' }; } return h('button', mergeData(data, componentData), slots().default); } }; var bAlert = { components: { bButtonClose: bBtnClose }, render: function render(h) { if (!this.localShow) { // If not showing, render placeholder return h(false); } var dismissBtn = h(false); if (this.dismissible) { // Add dismiss button dismissBtn = h('b-button-close', { attrs: { 'aria-label': this.dismissLabel }, on: { click: this.dismiss } }, [this.$slots.dismiss]); } var alert = h('div', { class: this.classObject, attrs: { role: 'alert', 'aria-live': 'polite', 'aria-atomic': true } }, [dismissBtn, this.$slots.default]); return !this.fade ? alert : h('transition', { props: { name: 'fade', appear: true } }, [alert]); }, model: { prop: 'show', event: 'input' }, data: function data() { return { countDownTimerId: null, dismissed: false }; }, computed: { classObject: function classObject() { return ['alert', this.alertVariant, this.dismissible ? 'alert-dismissible' : '']; }, alertVariant: function alertVariant() { var variant = this.variant; return 'alert-' + variant; }, localShow: function localShow() { return !this.dismissed && (this.countDownTimerId || this.show); } }, props: { variant: { type: String, default: 'info' }, dismissible: { type: Boolean, default: false }, dismissLabel: { type: String, default: 'Close' }, show: { type: [Boolean, Number], default: false }, fade: { type: Boolean, default: false } }, watch: { show: function show() { this.showChanged(); } }, mounted: function mounted() { this.showChanged(); }, destroyed /* istanbul ignore next */: function destroyed() { this.clearCounter(); }, methods: { dismiss: function dismiss() { this.clearCounter(); this.dismissed = true; this.$emit('dismissed'); this.$emit('input', false); if (typeof this.show === 'number') { this.$emit('dismiss-count-down', 0); this.$emit('input', 0); } else { this.$emit('input', false); } }, clearCounter: function clearCounter() { if (this.countDownTimerId) { clearInterval(this.countDownTimerId); this.countDownTimerId = null; } }, showChanged: function showChanged() { var _this = this; // Reset counter status this.clearCounter(); // Reset dismiss status this.dismissed = false; // No timer for boolean values if (this.show === true || this.show === false || this.show === null || this.show === 0) { return; } // Start counter var dismissCountDown = this.show; this.countDownTimerId = setInterval(function () { if (dismissCountDown < 1) { _this.dismiss(); return; } dismissCountDown--; _this.$emit('dismiss-count-down', dismissCountDown); _this.$emit('input', dismissCountDown); }, 1000); } } }; /** * Register a component plugin as being loaded. returns true if compoent plugin already registered * @param {object} Vue * @param {string} Component name * @param {object} Component definition */ function registerComponent(Vue, name, def) { Vue._bootstrap_vue_components_ = Vue._bootstrap_vue_components_ || {}; var loaded = Vue._bootstrap_vue_components_[name]; if (!loaded && def && name) { Vue._bootstrap_vue_components_[name] = true; Vue.component(name, def); } return loaded; } /** * Register a group of components as being loaded. * @param {object} Vue * @param {object} Object of component definitions */ function registerComponents(Vue, components) { for (var component in components) { registerComponent(Vue, component, components[component]); } } /** * Register a directive as being loaded. returns true if directive plugin already registered * @param {object} Vue * @param {string} Directive name * @param {object} Directive definition */ function registerDirective(Vue, name, def) { Vue._bootstrap_vue_directives_ = Vue._bootstrap_vue_directives_ || {}; var loaded = Vue._bootstrap_vue_directives_[name]; if (!loaded && def && name) { Vue._bootstrap_vue_directives_[name] = true; Vue.directive(name, def); } return loaded; } /** * Register a group of directives as being loaded. * @param {object} Vue * @param {object} Object of directive definitions */ function registerDirectives(Vue, directives) { for (var directive in directives) { registerDirective(Vue, directive, directives[directive]); } } /** * Install plugin if window.Vue available * @param {object} Plugin definition */ function vueUse(VuePlugin) { if (typeof window !== 'undefined' && window.Vue) { window.Vue.use(VuePlugin); } } var components = { bAlert: bAlert }; var VuePlugin = { install: function install(Vue) { registerComponents(Vue, components); } }; vueUse(VuePlugin); /** * Aliasing Object[method] allows the minifier to shorten methods to a single character variable, * as well as giving BV a chance to inject polyfills. * As long as we avoid * - import * as Object from "utils/object" * all unused exports should be removed by tree-shaking. */ // @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign if (typeof Object.assign !== 'function') { Object.assign = function (target, varArgs) { // .length of function is 2 if (target == null) { // TypeError if undefined or null throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource != null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }; } // @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Polyfill if (!Object.is) { Object.is = function (x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN // eslint-disable-next-line no-self-compare return x !== x && y !== y; } }; } var assign = Object.assign; var keys = Object.keys; var defineProperties = Object.defineProperties; var defineProperty$1 = Object.defineProperty; var create = Object.create; function readonlyDescriptor() { return { enumerable: true, configurable: false, writable: false }; } // Production steps of ECMA-262, Edition 6, 22.1.2.1 // es6-ified by @alexsasharegan if (!Array.from) { Array.from = function () { var toStr = Object.prototype.toString; var isCallable = function isCallable(fn) { return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; }; var toInteger = function toInteger(value) { var number = Number(value); if (isNaN(number)) { return 0; } if (number === 0 || !isFinite(number)) { return number; } return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); }; var maxSafeInteger = Math.pow(2, 53) - 1; var toLength = function toLength(value) { return Math.min(Math.max(toInteger(value), 0), maxSafeInteger); }; // The length property of the from method is 1. return function from(arrayLike /*, mapFn, thisArg */) { // 1. Let C be the this value. var C = this; // 2. Let items be ToObject(arrayLike). var items = Object(arrayLike); // 3. ReturnIfAbrupt(items). if (arrayLike == null) { throw new TypeError('Array.from requires an array-like object - not null or undefined'); } // 4. If mapfn is undefined, then let mapping be false. var mapFn = arguments.length > 1 ? arguments[1] : void undefined; var T = void 0; if (typeof mapFn !== 'undefined') { // 5. else // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. if (!isCallable(mapFn)) { throw new TypeError('Array.from: when provided, the second argument must be a function'); } // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. if (arguments.length > 2) { T = arguments[2]; } } // 10. Let lenValue be Get(items, "length"). // 11. Let len be ToLength(lenValue). var len = toLength(items.length); // 13. If IsConstructor(C) is true, then // 13. a. Let A be the result of calling the [[Construct]] internal method // of C with an argument list containing the single item len. // 14. a. Else, Let A be ArrayCreate(len). var A = isCallable(C) ? Object(new C(len)) : new Array(len); // 16. Let k be 0. var k = 0; // 17. Repeat, while k < len… (also steps a - h) var kValue = void 0; while (k < len) { kValue = items[k]; if (mapFn) { A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); } else { A[k] = kValue; } k += 1; } // 18. Let putStatus be Put(A, "length", len, true). A.length = len; // 20. Return A. return A; }; }(); } // https://tc39.github.io/ecma262/#sec-array.prototype.find // Needed for IE support if (!Array.prototype.find) { // eslint-disable-next-line no-extend-native Object.defineProperty(Array.prototype, 'find', { value: function value(predicate) { // 1. Let O be ? ToObject(this value). if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let len be ? ToLength(? Get(O, "length")). var len = o.length >>> 0; // 3. If IsCallable(predicate) is false, throw a TypeError exception. if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. var thisArg = arguments[1]; // 5. Let k be 0. var k = 0; // 6. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). // d. If testResult is true, return kValue. var kValue = o[k]; if (predicate.call(thisArg, kValue, k, o)) { return kValue; } // e. Increase k by 1. k++; } // 7. Return undefined. return undefined; } }); } if (!Array.isArray) { Array.isArray = function (arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }; } // Static var from = Array.from; var isArray = Array.isArray; // Instance var arrayIncludes = function arrayIncludes(array, value) { return array.indexOf(value) !== -1; }; function concat() { return Array.prototype.concat.apply([], arguments); } function identity(x) { return x; } /** * Given an array of properties or an object of property keys, * plucks all the values off the target object. * @param {{}|string[]} keysToPluck * @param {{}} objToPluck * @param {Function} transformFn * @return {{}} */ function pluckProps(keysToPluck, objToPluck) { var transformFn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : identity; return (isArray(keysToPluck) ? keysToPluck.slice() : keys(keysToPluck)).reduce(function (memo, prop) { // eslint-disable-next-line no-sequences return memo[transformFn(prop)] = objToPluck[prop], memo; }, {}); } /** * The Link component is used in many other BV components. * As such, sharing its props makes supporting all its features easier. * However, some components need to modify the defaults for their own purpose. * Prefer sharing a fresh copy of the props to ensure mutations * do not affect other component references to the props. * * https://github.com/vuejs/vue-router/blob/dev/src/components/link.js * @return {{}} */ function propsFactory() { return { href: { type: String, default: null }, rel: { type: String, default: null }, target: { type: String, default: '_self' }, active: { type: Boolean, default: false }, activeClass: { type: String, default: 'active' }, append: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, event: { type: [String, Array], default: 'click' }, exact: { type: Boolean, default: false }, exactActiveClass: { type: String, default: 'active' }, replace: { type: Boolean, default: false }, routerTag: { type: String, default: 'a' }, to: { type: [String, Object], default: null } }; } function pickLinkProps(propsToPick) { var freshLinkProps = propsFactory(); // Normalize everything to array. propsToPick = concat(propsToPick); return keys(freshLinkProps).reduce(function (memo, prop) { if (arrayIncludes(propsToPick, prop)) { memo[prop] = freshLinkProps[prop]; } return memo; }, {}); } function computeTag(props, parent) { return Boolean(parent.$router) && props.to && !props.disabled ? 'router-link' : 'a'; } function computeHref(_ref, tag) { var disabled = _ref.disabled, href = _ref.href, to = _ref.to; // We've already checked the parent.$router in computeTag, // so router-link means live router. // When deferring to Vue Router's router-link, // don't use the href attr at all. // Must return undefined for router-link to populate href. if (tag === 'router-link') return void 0; // If href explicitly provided if (href) return href; // Reconstruct href when `to` used, but no router if (to) { // Fallback to `to` prop (if `to` is a string) if (typeof to === 'string') return to; // Fallback to `to.path` prop (if `to` is an object) if ((typeof to === 'undefined' ? 'undefined' : _typeof(to)) === 'object' && typeof to.path === 'string') return to.path; } // If nothing is provided use '#' return '#'; } function computeRel(_ref2) { var target = _ref2.target, rel = _ref2.rel; if (target === '_blank' && rel === null) { return 'noopener'; } return rel || null; } function clickHandlerFactory(_ref3) { var disabled = _ref3.disabled, tag = _ref3.tag, href = _ref3.href, suppliedHandler = _ref3.suppliedHandler, parent = _ref3.parent; var isRouterLink = tag === 'router-link'; return function onClick(e) { if (disabled && e instanceof Event) { // Stop event from bubbling up. e.stopPropagation(); // Kill the event loop attached to this specific EventTarget. e.stopImmediatePropagation(); } else { parent.$root.$emit('clicked::link', e); if (isRouterLink && e.target.__vue__) { e.target.__vue__.$emit('click', e); } if (typeof suppliedHandler === 'function') { suppliedHandler.apply(undefined, arguments); } } if (!isRouterLink && href === '#' || disabled) { // Stop scroll-to-top behavior or navigation. e.preventDefault(); } }; } var bLink = { functional: true, props: propsFactory(), render: function render(h, _ref4) { var props = _ref4.props, data = _ref4.data, parent = _ref4.parent, children = _ref4.children; var tag = computeTag(props, parent); var rel = computeRel(props); var href = computeHref(props, tag); var eventType = tag === 'router-link' ? 'nativeOn' : 'on'; var suppliedHandler = (data[eventType] || {}).click; var handlers = { click: clickHandlerFactory({ tag: tag, href: href, disabled: props.disabled, suppliedHandler: suppliedHandler, parent: parent }) }; var componentData = mergeData(data, { class: [props.active ? props.exact ? props.exactActiveClass : props.activeClass : null, { disabled: props.disabled }], attrs: { rel: rel, href: href, target: props.target, tabindex: props.disabled ? '-1' : data.attrs ? data.attrs.tabindex : null, 'aria-disabled': tag === 'a' && props.disabled ? 'true' : null }, props: assign(props, { tag: props.routerTag }) }); // If href prop exists on router-link (even undefined or null) it fails working on SSR if (!componentData.attrs.href) { delete componentData.attrs.href; } // We want to overwrite any click handler since our callback // will invoke the supplied handler if !props.disabled componentData[eventType] = assign(componentData[eventType] || {}, handlers); return h(tag, componentData, children); } }; var linkProps = propsFactory(); delete linkProps.href.default; delete linkProps.to.default; var props$2 = assign(linkProps, { tag: { type: String, default: 'span' }, variant: { type: String, default: 'secondary' }, pill: { type: Boolean, default: false } }); var bBadge = { functional: true, props: props$2, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var tag = !props.href && !props.to ? props.tag : bLink; var componentData = { staticClass: 'badge', class: [!props.variant ? 'badge-secondary' : 'badge-' + props.variant, { 'badge-pill': Boolean(props.pill), active: props.active, disabled: props.disabled }], props: pluckProps(linkProps, props) }; return h(tag, mergeData(data, componentData), children); } }; var components$1 = { bBadge: bBadge }; var VuePlugin$1 = { install: function install(Vue) { registerComponents(Vue, components$1); } }; vueUse(VuePlugin$1); var props$3 = assign(propsFactory(), { text: { type: String, default: null }, active: { type: Boolean, default: false }, href: { type: String, default: '#' }, ariaCurrent: { type: String, default: 'location' } }); var BreadcrumbLink = { functional: true, props: props$3, render: function render(h, _ref) { var suppliedProps = _ref.props, data = _ref.data, children = _ref.children; var tag = suppliedProps.active ? 'span' : bLink; var componentData = { props: pluckProps(props$3, suppliedProps) }; if (suppliedProps.active) { componentData.attrs = { 'aria-current': suppliedProps.ariaCurrent }; } else { componentData.attrs = { href: suppliedProps.href }; } return h(tag, mergeData(data, componentData), children || suppliedProps.text); } }; var props$4 = assign({}, props$3, { text: { type: String, default: null }, href: { type: String, default: null } }); var BreadcrumbItem = { functional: true, props: props$4, render: function render(h, _ref) { var props$$1 = _ref.props, data = _ref.data, children = _ref.children; return h('li', mergeData(data, { staticClass: 'breadcrumb-item', class: { active: props$$1.active }, attrs: { role: 'presentation' } }), [h(BreadcrumbLink, { props: props$$1 }, children)]); } }; var props$5 = { items: { type: Array, default: null } }; var bBreadcrumb = { functional: true, props: props$5, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var childNodes = children; // Build child nodes from items if given. if (isArray(props.items)) { var activeDefined = false; childNodes = props.items.map(function (item, idx) { if ((typeof item === 'undefined' ? 'undefined' : _typeof(item)) !== 'object') { item = { text: item }; } // Copy the value here so we can normalize it. var active = item.active; if (active) { activeDefined = true; } if (!active && !activeDefined) { // Auto-detect active by position in list. active = idx + 1 === props.items.length; } return h(BreadcrumbItem, { props: assign({}, item, { active: active }) }); }); } return h('ol', mergeData(data, { staticClass: 'breadcrumb' }), childNodes); } }; var components$2 = { bBreadcrumb: bBreadcrumb, bBreadcrumbItem: BreadcrumbItem, bBreadcrumbLink: BreadcrumbLink }; var VuePlugin$2 = { install: function install(Vue) { registerComponents(Vue, components$2); } }; vueUse(VuePlugin$2); // Determine if an element is an HTML Element var isElement = function isElement(el) { return el && el.nodeType === Node.ELEMENT_NODE; }; // Determine if an HTML element is visible - Faster than CSS check var isVisible = function isVisible(el) { return isElement(el) && document.body.contains(el) && el.getBoundingClientRect().height > 0 && el.getBoundingClientRect().width > 0; }; // Determine if an element is disabled var isDisabled = function isDisabled(el) { return !isElement(el) || el.disabled || el.classList.contains('disabled') || Boolean(el.getAttribute('disabled')); }; // Cause/wait-for an element to reflow it's content (adjusting it's height/width) var reflow = function reflow(el) { // requsting an elements offsetHight will trigger a reflow of the element content return isElement(el) && el.offsetHeight; }; // Select all elements matching selector. Returns [] if none found var selectAll = function selectAll(selector, root) { if (!isElement(root)) { root = document; } return from(root.querySelectorAll(selector)); }; // Select a single element, returns null if not found var select = function select(selector, root) { if (!isElement(root)) { root = document; } return root.querySelector(selector) || null; }; // Determine if an element matches a selector var matches = function matches(el, selector) { if (!isElement(el)) { return false; } // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill // Prefer native implementations over polyfill function var proto = Element.prototype; var Matches = proto.matches || proto.matchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector || proto.webkitMatchesSelector || /* istanbul ignore next */ function (sel) { var element = this; var m = selectAll(sel, element.document || element.ownerDocument); var i = m.length; // eslint-disable-next-line no-empty while (--i >= 0 && m.item(i) !== element) {} return i > -1; }; return Matches.call(el, selector); }; // Finds closest element matching selector. Returns null if not found var closest = function closest(selector, root) { if (!isElement(root)) { return null; } // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest // Since we dont support IE < 10, we can use the "Matches" version of the polyfill for speed // Prefer native implementation over polyfill function var Closest = Element.prototype.closest || /* istanbul ignore next */ function (sel) { var element = this; if (!document.documentElement.contains(element)) { return null; } do { // Use our "patched" matches function if (matches(element, sel)) { return element; } element = element.parentElement; } while (element !== null); return null; }; var el = Closest.call(root, selector); // Emulate jQuery closest and return null if match is the passed in element (root) return el === root ? null : el; }; // Get an element given an ID var getById = function getById(id) { return document.getElementById(/^#/.test(id) ? id.slice(1) : id) || null; }; // Add a class to an element var addClass = function addClass(el, className) { if (className && isElement(el)) { el.classList.add(className); } }; // Remove a class from an element var removeClass = function removeClass(el, className) { if (className && isElement(el)) { el.classList.remove(className); } }; // Test if an element has a class var hasClass = function hasClass(el, className) { if (className && isElement(el)) { return el.classList.contains(className); } return false; }; // Set an attribute on an element var setAttr = function setAttr(el, attr, value) { if (attr && isElement(el)) { el.setAttribute(attr, value); } }; // Remove an attribute from an element var removeAttr = function removeAttr(el, attr) { if (attr && isElement(el)) { el.removeAttribute(attr); } }; // Get an attribute value from an element (returns null if not found) var getAttr = function getAttr(el, attr) { if (attr && isElement(el)) { return el.getAttribute(attr); } return null; }; // Determine if an attribute exists on an element (returns true or false, or null if element not found) var hasAttr = function hasAttr(el, attr) { if (attr && isElement(el)) { return el.hasAttribute(attr); } return null; }; // Return the Bounding Client Rec of an element. Retruns null if not an element var getBCR = function getBCR(el) { return isElement(el) ? el.getBoundingClientRect() : null; }; // Get computed style object for an element var getCS = function getCS(el) { return isElement(el) ? window.getComputedStyle(el) : {}; }; // Return an element's offset wrt document element // https://j11y.io/jquery/#v=git&fn=jQuery.fn.offset var offset = function offset(el) { if (isElement(el)) { if (!el.getClientRects().length) { return { top: 0, left: 0 }; } var bcr = getBCR(el); var win = el.ownerDocument.defaultView; return { top: bcr.top + win.pageYOffset, left: bcr.left + win.pageXOffset }; } }; // Return an element's offset wrt to it's offsetParent // https://j11y.io/jquery/#v=git&fn=jQuery.fn.position var position = function position(el) { if (!isElement(el)) { return; } var parentOffset = { top: 0, left: 0 }; var offsetSelf = void 0; var offsetParent = void 0; if (getCS(el).position === 'fixed') { offsetSelf = getBCR(el); } else { offsetSelf = offset(el); var doc = el.ownerDocument; offsetParent = el.offsetParent || doc.documentElement; while (offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && getCS(offsetParent).position === 'static') { offsetParent = offsetParent.parentNode; } if (offsetParent && offsetParent !== el && offsetParent.nodeType === Node.ELEMENT_NODE) { parentOffset = offset(offsetParent); parentOffset.top += parseFloat(getCS(offsetParent).borderTopWidth); parentOffset.left += parseFloat(getCS(offsetParent).borderLeftWidth); } } return { top: offsetSelf.top - parentOffset.top - parseFloat(getCS(el).marginTop), left: offsetSelf.left - parentOffset.left - parseFloat(getCS(el).marginLeft) }; }; // Attach an event listener to an element var eventOn = function eventOn(el, evtName, handler) { if (el && el.addEventListener) { el.addEventListener(evtName, handler); } }; // Remove an event listener from an element var eventOff = function eventOff(el, evtName, handler) { if (el && el.removeEventListener) { el.removeEventListener(evtName, handler); } }; var btnProps = { block: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, size: { type: String, default: null }, variant: { type: String, default: null }, type: { type: String, default: 'button' }, pressed: { // tri-state prop: true, false or null // => on, off, not a toggle type: Boolean, default: null } }; var linkProps$1 = propsFactory(); delete linkProps$1.href.default; delete linkProps$1.to.default; var linkPropKeys = keys(linkProps$1); var props$6 = assign(linkProps$1, btnProps); function handleFocus(evt) { if (evt.type === 'focusin') { addClass(evt.target, 'focus'); } else if (evt.type === 'focusout') { removeClass(evt.target, 'focus'); } } var bBtn = { functional: true, props: props$6, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, listeners = _ref.listeners, children = _ref.children; var isLink = Boolean(props.href || props.to); var isToggle = typeof props.pressed === 'boolean'; var on = { click: function click(e) { if (props.disabled && e instanceof Event) { e.stopPropagation(); e.preventDefault(); } else if (isToggle) { // Concat will normalize the value to an array // without double wrapping an array value in an array. concat(listeners['update:pressed']).forEach(function (fn) { if (typeof fn === 'function') { fn(!props.pressed); } }); } } }; if (isToggle) { on.focusin = handleFocus; on.focusout = handleFocus; } var componentData = { staticClass: 'btn', class: [props.variant ? 'btn-' + props.variant : 'btn-secondary', (_ref2 = {}, defineProperty(_ref2, 'btn-' + props.size, Boolean(props.size)), defineProperty(_ref2, 'btn-block', props.block), defineProperty(_ref2, 'disabled', props.disabled), defineProperty(_ref2, 'active', props.pressed), _ref2)], props: isLink ? pluckProps(linkPropKeys, props) : null, attrs: { type: isLink ? null : props.type, disabled: isLink ? null : props.disabled, // Data attribute not used for js logic, // but only for BS4 style selectors. 'data-toggle': isToggle ? 'button' : null, 'aria-pressed': isToggle ? String(props.pressed) : null, // Tab index is used when the component becomes a link. // Links are tabable, but don't allow disabled, // so we mimic that functionality by disabling tabbing. tabindex: props.disabled && isLink ? '-1' : data.attrs ? data.attrs['tabindex'] : null }, on: on }; return h(isLink ? bLink : 'button', mergeData(data, componentData), children); } }; var components$3 = { bButton: bBtn, bBtn: bBtn, bButtonClose: bBtnClose, bBtnClose: bBtnClose }; var VuePlugin$3 = { install: function install(Vue) { registerComponents(Vue, components$3); } }; vueUse(VuePlugin$3); var props$7 = { vertical: { type: Boolean, default: false }, size: { type: String, default: null, validator: function validator(size) { return arrayIncludes(['sm', '', 'lg'], size); } }, tag: { type: String, default: 'div' }, ariaRole: { type: String, default: 'group' } }; var bButtonGroup = { functional: true, props: props$7, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { class: defineProperty({ 'btn-group': !props.vertical, 'btn-group-vertical': props.vertical }, 'btn-group-' + props.size, Boolean(props.size)), attrs: { 'role': props.ariaRole } }), children); } }; var components$4 = { bButtonGroup: bButtonGroup, bBtnGroup: bButtonGroup }; var VuePlugin$4 = { install: function install(Vue) { registerComponents(Vue, components$4); } }; vueUse(VuePlugin$4); /* * Key Codes (events) */ var KeyCodes = { SPACE: 32, ENTER: 13, ESC: 27, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, PAGEUP: 33, PAGEDOWN: 34, HOME: 36, END: 35 }; var ITEM_SELECTOR = ['.btn:not(.disabled):not([disabled]):not(.dropdown-item)', '.form-control:not(.disabled):not([disabled])', 'select:not(.disabled):not([disabled])', 'input[type="checkbox"]:not(.disabled)', 'input[type="radio"]:not(.disabled)'].join(','); var bButtonToolbar = { render: function render(h) { return h('div', { class: this.classObject, attrs: { role: 'toolbar', tabindex: this.keyNav ? '0' : null }, on: { focusin: this.onFocusin, keydown: this.onKeydown } }, [this.$slots.default]); }, computed: { classObject: function classObject() { return ['btn-toolbar', this.justify && !this.vertical ? 'justify-content-between' : '']; } }, props: { justify: { type: Boolean, default: false }, keyNav: { type: Boolean, default: false } }, methods: { onFocusin: function onFocusin(evt) { if (evt.target === this.$el) { evt.preventDefault(); evt.stopPropagation(); this.focusFirst(evt); } }, onKeydown: function onKeydown(evt) { if (!this.keyNav) { return; } var key = evt.keyCode; var shift = evt.shiftKey; if (key === KeyCodes.UP || key === KeyCodes.LEFT) { evt.preventDefault(); evt.stopPropagation(); if (shift) { this.focusFirst(evt); } else { this.focusNext(evt, true); } } else if (key === KeyCodes.DOWN || key === KeyCodes.RIGHT) { evt.preventDefault(); evt.stopPropagation(); if (shift) { this.focusLast(evt); } else { this.focusNext(evt, false); } } }, setItemFocus: function setItemFocus(item) { this.$nextTick(function () { item.focus(); }); }, focusNext: function focusNext(evt, prev) { var items = this.getItems(); if (items.length < 1) { return; } var index = items.indexOf(evt.target); if (prev && index > 0) { index--; } else if (!prev && index < items.length - 1) { index++; } if (index < 0) { index = 0; } this.setItemFocus(items[index]); }, focusFirst: function focusFirst(evt) { var items = this.getItems(); if (items.length > 0) { this.setItemFocus(items[0]); } }, focusLast: function focusLast(evt) { var items = this.getItems(); if (items.length > 0) { this.setItemFocus([items.length - 1]); } }, getItems: function getItems() { var items = selectAll(ITEM_SELECTOR, this.$el); items.forEach(function (item) { // Ensure tabfocus is -1 on any new elements item.tabIndex = -1; }); return items.filter(function (el) { return isVisible(el); }); } }, mounted: function mounted() { if (this.keyNav) { // Pre-set the tabindexes if the markup does not include tabindex="-1" on the toolbar items this.getItems(); } } }; var components$5 = { bButtonToolbar: bButtonToolbar, bBtnToolbar: bButtonToolbar }; var VuePlugin$5 = { install: function install(Vue) { registerComponents(Vue, components$5); } }; vueUse(VuePlugin$5); var props$8 = { tag: { type: String, default: 'div' } }; var InputGroupText = { props: props$8, functional: true, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'input-group-text' }), children); } }; var propsFactory$1 = function propsFactory(append) { return { id: { type: String, default: null }, tag: { type: String, default: 'div' }, append: { type: Boolean, default: append }, isText: { type: Boolean, default: false } }; }; var InputGroupAddon = { functional: true, props: propsFactory$1(false), render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'input-group-' + (props.append ? 'append' : 'prepend'), attrs: { id: props.id } }), props.isText ? [h(InputGroupText, children)] : children); } }; var InputGroupPrepend = { functional: true, props: propsFactory$1(false), render: InputGroupAddon.render }; var InputGroupAppend = { functional: true, props: propsFactory$1(true), render: InputGroupAddon.render }; var props$9 = { id: { type: String, default: null }, size: { type: String, default: null }, prepend: { type: String, default: null }, append: { type: String, default: null }, tag: { type: String, default: 'div' } }; var bInputGroup = { functional: true, props: props$9, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, slots = _ref.slots; var $slots = slots(); var childNodes = []; // Prepend prop if (props.prepend) { childNodes.push(h(InputGroupPrepend, [h(InputGroupText, { domProps: { innerHTML: props.prepend } })])); } // Prepend slot if ($slots.prepend) { childNodes.push(h(InputGroupPrepend, $slots.prepend)); } // Default slot childNodes.push($slots.default); // Append prop if (props.append) { childNodes.push(h(InputGroupAppend, [h(InputGroupText, { domProps: { innerHTML: props.append } })])); } // Append slot if ($slots.append) { childNodes.push(h(InputGroupAppend, $slots.append)); } return h(props.tag, mergeData(data, { staticClass: 'input-group', class: defineProperty({}, 'input-group-' + props.size, Boolean(props.size)), attrs: { id: props.id || null, role: 'group' } }), childNodes); } }; var components$6 = { bInputGroup: bInputGroup, bInputGroupAddon: InputGroupAddon, bInputGroupPrepend: InputGroupPrepend, bInputGroupAppend: InputGroupAppend, bInputGroupText: InputGroupText }; var VuePlugin$6 = { install: function install(Vue) { registerComponents(Vue, components$6); } }; vueUse(VuePlugin$6); /** * @param {string} str */ function upperFirst(str) { if (typeof str !== 'string') { str = String(str); } return str.charAt(0).toUpperCase() + str.slice(1); } /** * @param {string} prefix * @param {string} value */ function prefixPropName(prefix, value) { return prefix + upperFirst(value); } /** * @param {string} str */ function lowerFirst(str) { if (typeof str !== 'string') { str = String(str); } return str.charAt(0).toLowerCase() + str.slice(1); } /** * @param {string} prefix * @param {string} value */ function unPrefixPropName(prefix, value) { return lowerFirst(value.replace(prefix, '')); } /** * @param {[]|{}} props * @param {Function} transformFn */ function copyProps(props) { var transformFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : identity; if (isArray(props)) { return props.map(transformFn); } // Props as an object. var copied = {}; for (var prop in props) { if (props.hasOwnProperty(prop)) { if ((typeof prop === 'undefined' ? 'undefined' : _typeof(prop)) === 'object') { copied[transformFn(prop)] = assign({}, props[prop]); } else { copied[transformFn(prop)] = props[prop]; } } } return copied; } var cardMixin = { props: { tag: { type: String, default: 'div' }, bgVariant: { type: String, default: null }, borderVariant: { type: String, default: null }, textVariant: { type: String, default: null } } }; var props$a = assign({}, copyProps(cardMixin.props, prefixPropName.bind(null, 'body')), { bodyClass: { type: [String, Object, Array], default: null }, title: { type: String, default: null }, titleTag: { type: String, default: 'h4' }, subTitle: { type: String, default: null }, subTitleTag: { type: String, default: 'h6' }, overlay: { type: Boolean, default: false } }); var CardBody = { functional: true, props: props$a, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, slots = _ref.slots; var cardBodyChildren = []; if (props.title) { cardBodyChildren.push(h(props.titleTag, { staticClass: 'card-title', domProps: { innerHTML: props.title } })); } if (props.subTitle) { cardBodyChildren.push(h(props.subTitleTag, { staticClass: 'card-subtitle mb-2 text-muted', domProps: { innerHTML: props.subTitle } })); } cardBodyChildren.push(slots().default); return h(props.bodyTag, mergeData(data, { staticClass: 'card-body', class: [(_ref2 = { 'card-img-overlay': props.overlay }, defineProperty(_ref2, 'bg-' + props.bodyBgVariant, Boolean(props.bodyBgVariant)), defineProperty(_ref2, 'border-' + props.bodyBorderVariant, Boolean(props.bodyBorderVariant)), defineProperty(_ref2, 'text-' + props.bodyTextVariant, Boolean(props.bodyTextVariant)), _ref2), props.bodyClass || {}] }), cardBodyChildren); } }; var props$b = assign({}, copyProps(cardMixin.props, prefixPropName.bind(null, 'header')), { header: { type: String, default: null }, headerClass: { type: [String, Object, Array], default: null } }); var CardHeader = { functional: true, props: props$b, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, slots = _ref.slots, children = _ref.children; return h(props.headerTag, mergeData(data, { staticClass: 'card-header', class: [props.headerClass, (_ref2 = {}, defineProperty(_ref2, 'bg-' + props.headerBgVariant, Boolean(props.headerBgVariant)), defineProperty(_ref2, 'border-' + props.headerBorderVariant, Boolean(props.headerBorderVariant)), defineProperty(_ref2, 'text-' + props.headerTextVariant, Boolean(props.headerTextVariant)), _ref2)] }), children || [h('div', { domProps: { innerHTML: props.header } })]); } }; var props$c = assign({}, copyProps(cardMixin.props, prefixPropName.bind(null, 'footer')), { footer: { type: String, default: null }, footerClass: { type: [String, Object, Array], default: null } }); var CardFooter = { functional: true, props: props$c, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, slots = _ref.slots, children = _ref.children; return h(props.footerTag, mergeData(data, { staticClass: 'card-footer', class: [props.footerClass, (_ref2 = {}, defineProperty(_ref2, 'bg-' + props.footerBgVariant, Boolean(props.footerBgVariant)), defineProperty(_ref2, 'border-' + props.footerBorderVariant, Boolean(props.footerBorderVariant)), defineProperty(_ref2, 'text-' + props.footerTextVariant, Boolean(props.footerTextVariant)), _ref2)] }), children || [h('div', { domProps: { innerHTML: props.footer } })]); } }; var props$d = { src: { type: String, default: null, required: true }, alt: { type: String, default: null }, top: { type: Boolean, default: false }, bottom: { type: Boolean, default: false }, fluid: { type: Boolean, default: false } }; var CardImg = { functional: true, props: props$d, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, slots = _ref.slots; var staticClass = 'card-img'; if (props.top) { staticClass += '-top'; } else if (props.bottom) { staticClass += '-bottom'; } return h('img', mergeData(data, { staticClass: staticClass, class: { 'img-fluid': props.fluid }, attrs: { src: props.src, alt: props.alt } })); } }; var cardImgProps = copyProps(props$d, prefixPropName.bind(null, 'img')); cardImgProps.imgSrc.required = false; var props$e = assign({}, props$a, props$b, props$c, cardImgProps, copyProps(cardMixin.props), { align: { type: String, default: null }, noBody: { type: Boolean, default: false } }); var bCard = { functional: true, props: props$e, render: function render(h, _ref) { var _class; var props$$1 = _ref.props, data = _ref.data, slots = _ref.slots, children = _ref.children; // The order of the conditionals matter. // We are building the component markup in order. var childNodes = []; var $slots = slots(); var img = props$$1.imgSrc ? h(CardImg, { props: pluckProps(cardImgProps, props$$1, unPrefixPropName.bind(null, 'img')) }) : null; if (img) { // Above the header placement. if (props$$1.imgTop || !props$$1.imgBottom) { childNodes.push(img); } } if (props$$1.header || $slots.header) { childNodes.push(h(CardHeader, { props: pluckProps(props$b, props$$1) }, $slots.header)); } if (props$$1.noBody) { childNodes.push($slots.default); } else { childNodes.push(h(CardBody, { props: pluckProps(props$a, props$$1) }, $slots.default)); } if (props$$1.footer || $slots.footer) { childNodes.push(h(CardFooter, { props: pluckProps(props$c, props$$1) }, $slots.footer)); } if (img && props$$1.imgBottom) { // Below the footer placement. childNodes.push(img); } return h(props$$1.tag, mergeData(data, { staticClass: 'card', class: (_class = {}, defineProperty(_class, 'text-' + props$$1.align, Boolean(props$$1.align)), defineProperty(_class, 'bg-' + props$$1.bgVariant, Boolean(props$$1.bgVariant)), defineProperty(_class, 'border-' + props$$1.borderVariant, Boolean(props$$1.borderVariant)), defineProperty(_class, 'text-' + props$$1.textVariant, Boolean(props$$1.textVariant)), _class) }), childNodes); } }; var props$f = { tag: { type: String, default: 'div' }, deck: { type: Boolean, default: false }, columns: { type: Boolean, default: false } }; var bCardGroup = { functional: true, props: props$f, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var staticClass = 'card-group'; if (props.columns) { staticClass = 'card-columns'; } if (props.deck) { staticClass = 'card-deck'; } return h(props.tag, mergeData(data, { staticClass: staticClass }), children); } }; var components$7 = { bCard: bCard, bCardHeader: CardHeader, bCardBody: CardBody, bCardFooter: CardFooter, bCardImg: CardImg, bCardGroup: bCardGroup }; var VuePlugin$7 = { install: function install(Vue) { registerComponents(Vue, components$7); } }; vueUse(VuePlugin$7); /** * Observe a DOM element changes, falls back to eventListener mode * @param {Element} el The DOM element to observe * @param {Function} callback callback to be called on change * @param {object} [opts={childList: true, subtree: true}] observe options * @see http://stackoverflow.com/questions/3219758 */ function observeDOM(el, callback, opts) { var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var eventListenerSupported = window.addEventListener; // Handle case where we might be passed a vue instance el = el ? el.$el || el : null; /* istanbul ignore next: dificult to test in JSDOM */ if (!isElement(el)) { // We can't observe somthing that isn't an element return null; } var obs = null; /* istanbul ignore next: dificult to test in JSDOM */ if (MutationObserver) { // Define a new observer obs = new MutationObserver(function (mutations) { var changed = false; // A Mutation can contain several change records, so we loop through them to see what has changed. // We break out of the loop early if any "significant" change has been detected for (var i = 0; i < mutations.length && !changed; i++) { // The muttion record var mutation = mutations[i]; // Mutation Type var type = mutation.type; // DOM Node (could be any DOM Node type - HTMLElement, Text, comment, etc) var target = mutation.target; if (type === 'characterData' && target.nodeType === Node.TEXT_NODE) { // We ignore nodes that are not TEXt (i.e. comments, etc) as they don't change layout changed = true; } else if (type === 'attributes') { changed = true; } else if (type === 'childList' && (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)) { // This includes HTMLElement and Text Nodes being added/removed/re-arranged changed = true; } } if (changed) { // We only call the callback if a change that could affect layout/size truely happened. callback(); } }); // Have the observer observe foo for changes in children, etc obs.observe(el, assign({ childList: true, subtree: true }, opts)); } else if (eventListenerSupported) { // Legacy interface. most likely not used in modern browsers el.addEventListener('DOMNodeInserted', callback, false); el.addEventListener('DOMNodeRemoved', callback, false); } // We return a reference to the observer so that obs.disconnect() can be called if necessary // To reduce overhead when the root element is hiiden return obs; } /* * SSR Safe Client Side ID attribute generation * */ var idMixin = { props: { id: { type: String, default: null } }, methods: { safeId: function safeId() { var suffix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var id = this.id || this.localId_ || null; if (!id) { return null; } suffix = String(suffix).replace(/\s+/g, '_'); return suffix ? id + '_' + suffix : id; } }, computed: { localId_: function localId_() { if (!this.$isServer && !this.id && typeof this._uid !== 'undefined') { return '__BVID__' + this._uid; } } } }; // Slide directional classes var DIRECTION = { next: { dirClass: 'carousel-item-left', overlayClass: 'carousel-item-next' }, prev: { dirClass: 'carousel-item-right', overlayClass: 'carousel-item-prev' } // Fallback Transition duration (with a little buffer) in ms };var TRANS_DURATION = 600 + 50; // Transition Event names var TransitionEndEvents = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'otransitionend oTransitionEnd', transition: 'transitionend' // Return the browser specific transitionEnd event name };function getTransisionEndEvent(el) { for (var name in TransitionEndEvents) { if (el.style[name] !== undefined) { return TransitionEndEvents[name]; } } // fallback return null; } var bCarousel = { mixins: [idMixin], render: function render(h) { var _this = this; // Wrapper for slides var inner = h('div', { ref: 'inner', class: ['carousel-inner'], attrs: { id: this.safeId('__BV_inner_'), role: 'list' } }, [this.$slots.default]); // Prev and Next Controls var controls = h(false); if (this.controls) { controls = [h('a', { class: ['carousel-control-prev'], attrs: { href: '#', role: 'button', 'aria-controls': this.safeId('__BV_inner_') }, on: { click: function click(evt) { evt.preventDefault(); evt.stopPropagation(); _this.prev(); }, keydown: function keydown(evt) { var keyCode = evt.keyCode; if (keyCode === KeyCodes.SPACE || keyCode === KeyCodes.ENTER) { evt.preventDefault(); evt.stopPropagation(); _this.prev(); } } } }, [h('span', { class: ['carousel-control-prev-icon'], attrs: { 'aria-hidden': 'true' } }), h('span', { class: ['sr-only'] }, [this.labelPrev])]), h('a', { class: ['carousel-control-next'], attrs: { href: '#', role: 'button', 'aria-controls': this.safeId('__BV_inner_') }, on: { click: function click(evt) { evt.preventDefault(); evt.stopPropagation(); _this.next(); }, keydown: function keydown(evt) { var keyCode = evt.keyCode; if (keyCode === KeyCodes.SPACE || keyCode === KeyCodes.ENTER) { evt.preventDefault(); evt.stopPropagation(); _this.next(); } } } }, [h('span', { class: ['carousel-control-next-icon'], attrs: { 'aria-hidden': 'true' } }), h('span', { class: ['sr-only'] }, [this.labelNext])])]; } // Indicators var indicators = h('ol', { class: ['carousel-indicators'], directives: [{ name: 'show', rawName: 'v-show', value: this.indicators, expression: 'indicators' }], attrs: { id: this.safeId('__BV_indicators_'), 'aria-hidden': this.indicators ? 'false' : 'true', 'aria-label': this.labelIndicators, 'aria-owns': this.safeId('__BV_inner_') } }, this.slides.map(function (slide, n) { return h('li', { key: 'slide_' + n, class: { active: n === _this.index }, attrs: { role: 'button', id: _this.safeId('__BV_indicator_' + (n + 1) + '_'), tabindex: _this.indicators ? '0' : '-1', 'aria-current': n === _this.index ? 'true' : 'false', 'aria-label': _this.labelGotoSlide + ' ' + (n + 1), 'aria-describedby': _this.slides[n].id || null, 'aria-controls': _this.safeId('__BV_inner_') }, on: { click: function click(evt) { _this.setSlide(n); }, keydown: function keydown(evt) { var keyCode = evt.keyCode; if (keyCode === KeyCodes.SPACE || keyCode === KeyCodes.ENTER) { evt.preventDefault(); evt.stopPropagation(); _this.setSlide(n); } } } }); })); // Return the carousel return h('div', { class: ['carousel', 'slide'], style: { background: this.background }, attrs: { role: 'region', id: this.safeId(), 'aria-busy': this.isSliding ? 'true' : 'false' }, on: { mouseenter: this.pause, mouseleave: this.restart, focusin: this.pause, focusout: this.restart, keydown: function keydown(evt) { var keyCode = evt.keyCode; if (keyCode === KeyCodes.LEFT || keyCode === KeyCodes.RIGHT) { evt.preventDefault(); evt.stopPropagation(); _this[keyCode === KeyCodes.LEFT ? 'prev' : 'next'](); } } } }, [inner, controls, indicators]); }, data: function data() { return { index: this.value || 0, isSliding: false, intervalId: null, transitionEndEvent: null, slides: [], direction: null }; }, props: { labelPrev: { type: String, default: 'Previous Slide' }, labelNext: { type: String, default: 'Next Slide' }, labelGotoSlide: { type: String, default: 'Goto Slide' }, labelIndicators: { type: String, default: 'Select a slide to display' }, interval: { type: Number, default: 5000 }, indicators: { type: Boolean, default: false }, controls: { type: Boolean, default: false }, imgWidth: { // Sniffed by carousel-slide type: [Number, String] }, imgHeight: { // Sniffed by carousel-slide type: [Number, String] }, background: { type: String }, value: { type: Number, default: 0 } }, computed: { isCycling: function isCycling() { return Boolean(this.intervalId); } }, methods: { // Set slide setSlide: function setSlide(slide) { var _this2 = this; // Don't animate when page is not visible if (typeof document !== 'undefined' && document.visibilityState && document.hidden) { return; } var len = this.slides.length; // Don't do anything if nothing to slide to if (len === 0) { return; } // Don't change slide while transitioning, wait until transition is done if (this.isSliding) { // Schedule slide after sliding complete this.$once('sliding-end', function () { return _this2.setSlide(slide); }); return; } // Make sure we have an integer (you never know!) slide = Math.floor(slide); // Set new slide index. Wrap around if necessary this.index = slide >= len ? 0 : slide >= 0 ? slide : len - 1; }, // Previous slide prev: function prev() { this.direction = 'prev'; this.setSlide(this.index - 1); }, // Next slide next: function next() { this.direction = 'next'; this.setSlide(this.index + 1); }, // Pause auto rotation pause: function pause() { if (this.isCycling) { clearInterval(this.intervalId); this.intervalId = null; if (this.slides[this.index]) { // Make current slide focusable for screen readers this.slides[this.index].tabIndex = 0; } } }, // Start auto rotate slides start: function start() { var _this3 = this; // Don't start if no interval, or if we are already running if (!this.interval || this.isCycling) { return; } this.slides.forEach(function (slide) { slide.tabIndex = -1; }); this.intervalId = setInterval(function () { _this3.next(); }, Math.max(1000, this.interval)); }, // Re-Start auto rotate slides when focus/hover leaves the carousel restart: function restart(evt) { if (!this.$el.contains(document.activeElement)) { this.start(); } }, // Update slide list updateSlides: function updateSlides() { this.pause(); // Get all slides as DOM elements this.slides = selectAll('.carousel-item', this.$refs.inner); var numSlides = this.slides.length; // Keep slide number in range var index = Math.max(0, Math.min(Math.floor(this.index), numSlides - 1)); this.slides.forEach(function (slide, idx) { var n = idx + 1; if (idx === index) { addClass(slide, 'active'); } else { removeClass(slide, 'active'); } setAttr(slide, 'aria-current', idx === index ? 'true' : 'false'); setAttr(slide, 'aria-posinset', String(n)); setAttr(slide, 'aria-setsize', String(numSlides)); slide.tabIndex = -1; }); // Set slide as active this.setSlide(index); this.start(); }, calcDirection: function calcDirection() { var direction = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var curIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var nextIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; if (!direction) { return nextIndex > curIndex ? DIRECTION.next : DIRECTION.prev; } return DIRECTION[direction]; } }, watch: { value: function value(newVal, oldVal) { if (newVal !== oldVal) { this.setSlide(newVal); } }, interval: function interval(newVal, oldVal) { if (newVal === oldVal) { return; } if (!newVal) { // Pausing slide show this.pause(); } else { // Restarting or Changing interval this.pause(); this.start(); } }, index: function index(val, oldVal) { var _this4 = this; if (val === oldVal || this.isSliding) { return; } // Determine sliding direction var direction = this.calcDirection(this.direction, oldVal, val); // Determine current and next slides var currentSlide = this.slides[oldVal]; var nextSlide = this.slides[val]; // Don't do anything if there aren't any slides to slide to if (!currentSlide || !nextSlide) { return; } // Start animating this.isSliding = true; this.$emit('sliding-start', val); // Update v-model this.$emit('input', this.index); nextSlide.classList.add(direction.overlayClass); // Trigger a reflow of next slide reflow(nextSlide); addClass(currentSlide, direction.dirClass); addClass(nextSlide, direction.dirClass); // Transition End handler var called = false; /* istanbul ignore next: dificult to test */ var onceTransEnd = function onceTransEnd(evt) { if (called) { return; } called = true; if (_this4.transitionEndEvent) { var events = _this4.transitionEndEvent.split(/\s+/); events.forEach(function (event) { eventOff(currentSlide, event, onceTransEnd); }); } _this4._animationTimeout = null; removeClass(nextSlide, direction.dirClass); removeClass(nextSlide, direction.overlayClass); addClass(nextSlide, 'active'); removeClass(currentSlide, 'active'); removeClass(currentSlide, direction.dirClass); removeClass(currentSlide, direction.overlayClass); setAttr(currentSlide, 'aria-current', 'false'); setAttr(nextSlide, 'aria-current', 'true'); setAttr(currentSlide, 'aria-hidden', 'true'); setAttr(nextSlide, 'aria-hidden', 'false'); currentSlide.tabIndex = -1; nextSlide.tabIndex = -1; if (!_this4.isCycling) { // Focus the next slide for screen readers if not in play mode nextSlide.tabIndex = 0; _this4.$nextTick(function () { nextSlide.focus(); }); } _this4.isSliding = false; _this4.direction = null; // Notify ourselves that we're done sliding (slid) _this4.$nextTick(function () { return _this4.$emit('sliding-end', val); }); }; // Clear transition classes after transition ends if (this.transitionEndEvent) { var events = this.transitionEndEvent.split(/\s+/); events.forEach(function (event) { eventOn(currentSlide, event, onceTransEnd); }); } // Fallback to setTimeout this._animationTimeout = setTimeout(onceTransEnd, TRANS_DURATION); } }, created: function created() { // Create private non-reactive props this._animationTimeout = null; }, mounted: function mounted() { // Cache current browser transitionend event name this.transitionEndEvent = getTransisionEndEvent(this.$el) || null; // Get all slides this.updateSlides(); // Observe child changes so we can update slide list observeDOM(this.$refs.inner, this.updateSlides.bind(this), { subtree: false, childList: true, attributes: true, attributeFilter: ['id'] }); }, /* istanbul ignore next: dificult to test */ beforeDestroy: function beforeDestroy() { clearInterval(this.intervalId); clearTimeout(this._animationTimeout); this.intervalId = null; this._animationTimeout = null; } }; // Blank image with fill template var BLANK_TEMPLATE = '' + '' + ''; function makeBlankImgSrc(width, height, color) { var src = encodeURIComponent(BLANK_TEMPLATE.replace('%{w}', String(width)).replace('%{h}', String(height)).replace('%{f}', color)); return 'data:image/svg+xml;charset=UTF-8,' + src; } var props$g = { src: { type: String, default: null }, alt: { type: String, default: null }, width: { type: [Number, String], default: null }, height: { type: [Number, String], default: null }, block: { type: Boolean, default: false }, fluid: { type: Boolean, default: false }, fluidGrow: { // Gives fluid images class `w-100` to make them grow to fit container type: Boolean, default: false }, rounded: { // rounded can be: // false: no rounding of corners // true: slightly rounded corners // 'top': top corners rounded // 'right': right corners rounded // 'bottom': bottom corners rounded // 'left': left corners rounded // 'circle': circle/oval // '0': force rounding off type: [Boolean, String], default: false }, thumbnail: { type: Boolean, default: false }, left: { type: Boolean, default: false }, right: { type: Boolean, default: false }, center: { type: Boolean, default: false }, blank: { type: Boolean, default: false }, blankColor: { type: String, default: 'transparent' } }; var bImg = { functional: true, props: props$g, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data; var src = props.src; var width = parseInt(props.width, 10) ? parseInt(props.width, 10) : null; var height = parseInt(props.height, 10) ? parseInt(props.height, 10) : null; var align = null; var block = props.block; if (props.blank) { if (!height && Boolean(width)) { height = width; } else if (!width && Boolean(height)) { width = height; } if (!width && !height) { width = 1; height = 1; } // Make a blank SVG image src = makeBlankImgSrc(width, height, props.blankColor || 'transparent'); } if (props.left) { align = 'float-left'; } else if (props.right) { align = 'float-right'; } else if (props.center) { align = 'mx-auto'; block = true; } return h('img', mergeData(data, { attrs: { 'src': src, 'alt': props.alt, 'width': width ? String(width) : null, 'height': height ? String(height) : null }, class: (_class = { 'img-thumbnail': props.thumbnail, 'img-fluid': props.fluid || props.fluidGrow, 'w-100': props.fluidGrow, 'rounded': props.rounded === '' || props.rounded === true }, defineProperty(_class, 'rounded-' + props.rounded, typeof props.rounded === 'string' && props.rounded !== ''), defineProperty(_class, align, Boolean(align)), defineProperty(_class, 'd-block', block), _class) })); } }; /** * Log a warning message to the console with bootstrap-vue formatting sugar. * @param {string} message */ /* istanbul ignore next */ function warn(message) { console.warn("[Bootstrap-Vue warn]: " + message); } var bCarouselSlide = { components: { bImg: bImg }, mixins: [idMixin], render: function render(h) { var $slots = this.$slots; var img = $slots.img; if (!img && (this.imgSrc || this.imgBlank)) { img = h('b-img', { props: { fluidGrow: true, block: true, src: this.imgSrc, blank: this.imgBlank, blankColor: this.imgBlankColor, width: this.computedWidth, height: this.computedHeight, alt: this.imgAlt } }); } var content = h(this.contentTag, { class: this.contentClasses }, [this.caption ? h(this.captionTag, { domProps: { innerHTML: this.caption } }) : h(false), this.text ? h(this.textTag, { domProps: { innerHTML: this.text } }) : h(false), $slots.default]); return h('div', { class: ['carousel-item'], style: { background: this.background }, attrs: { id: this.safeId(), role: 'listitem' } }, [img, content]); }, props: { imgSrc: { type: String, default: function _default() { if (this && this.src) { // Deprecate src warn("b-carousel-slide: prop 'src' has been deprecated. Use 'img-src' instead"); return this.src; } return null; } }, src: { // Deprecated: use img-src instead type: String }, imgAlt: { type: String }, imgWidth: { type: [Number, String] }, imgHeight: { type: [Number, String] }, imgBlank: { type: Boolean, default: false }, imgBlankColor: { type: String, default: 'transparent' }, contentVisibleUp: { type: String }, contentTag: { type: String, default: 'div' }, caption: { type: String }, captionTag: { type: String, default: 'h3' }, text: { type: String }, textTag: { type: String, default: 'p' }, background: { type: String } }, computed: { contentClasses: function contentClasses() { return ['carousel-caption', this.contentVisibleUp ? 'd-none' : '', this.contentVisibleUp ? 'd-' + this.contentVisibleUp + '-block' : '']; }, computedWidth: function computedWidth() { // Use local width, or try parent width return this.imgWidth || this.$parent.imgWidth; }, computedHeight: function computedHeight() { // Use local height, or try parent height return this.imgHeight || this.$parent.imgHeight; } } }; var components$8 = { bCarousel: bCarousel, bCarouselSlide: bCarouselSlide }; var VuePlugin$8 = { install: function install(Vue) { registerComponents(Vue, components$8); } }; vueUse(VuePlugin$8); var props$h = { tag: { type: String, default: 'div' }, fluid: { type: Boolean, default: false } }; var Container = { functional: true, props: props$h, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { class: { 'container': !props.fluid, 'container-fluid': props.fluid } }), children); } }; var COMMON_ALIGNMENT = ['start', 'end', 'center']; var props$i = { tag: { type: String, default: 'div' }, noGutters: { type: Boolean, default: false }, alignV: { type: String, default: null, validator: function validator(str) { return arrayIncludes(COMMON_ALIGNMENT.concat(['baseline', 'stretch']), str); } }, alignH: { type: String, default: null, validator: function validator(str) { return arrayIncludes(COMMON_ALIGNMENT.concat(['between', 'around']), str); } }, alignContent: { type: String, default: null, validator: function validator(str) { return arrayIncludes(COMMON_ALIGNMENT.concat(['between', 'around', 'stretch']), str); } } }; var bRow = { functional: true, props: props$i, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'row', class: (_class = { 'no-gutters': props.noGutters }, defineProperty(_class, 'align-items-' + props.alignV, props.alignV), defineProperty(_class, 'justify-content-' + props.alignH, props.alignH), defineProperty(_class, 'align-content-' + props.alignContent, props.alignContent), _class) }), children); } }; function memoize(fn) { var cache = create(null); return function memoizedFn() { var args = JSON.stringify(arguments); return cache[args] = cache[args] || fn.apply(null, arguments); }; } /** * Suffix can be a falsey value so nothing is appended to string. * (helps when looping over props & some shouldn't change) * Use data last parameters to allow for currying. * @param {string} suffix * @param {string} str */ function suffixPropName(suffix, str) { return str + (suffix ? upperFirst(suffix) : ''); } /** * Generates a prop object with a type of * [Boolean, String, Number] */ function boolStrNum() { return { type: [Boolean, String, Number], default: false }; } /** * Generates a prop object with a type of * [String, Number] */ function strNum() { return { type: [String, Number], default: null }; } var computeBkPtClass = memoize(function computeBkPt(type, breakpoint, val) { var className = type; if (val === false || val === null || val === undefined) { return undefined; } if (breakpoint) { className += '-' + breakpoint; } // Handling the boolean style prop when accepting [Boolean, String, Number] // means Vue will not convert to sm: true for us. // Since the default is false, an empty string indicates the prop's presence. if (type === 'col' && (val === '' || val === true)) { // .col-md return className.toLowerCase(); } // .order-md-6 className += '-' + val; return className.toLowerCase(); }); var BREAKPOINTS = ['sm', 'md', 'lg', 'xl']; // Supports classes like: .col-sm, .col-md-6, .col-lg-auto var breakpointCol = BREAKPOINTS.reduce( // eslint-disable-next-line no-sequences function (propMap, breakpoint) { return propMap[breakpoint] = boolStrNum(), propMap; }, create(null)); // Supports classes like: .offset-md-1, .offset-lg-12 var breakpointOffset = BREAKPOINTS.reduce( // eslint-disable-next-line no-sequences function (propMap, breakpoint) { return propMap[suffixPropName(breakpoint, 'offset')] = strNum(), propMap; }, create(null)); // Supports classes like: .order-md-1, .order-lg-12 var breakpointOrder = BREAKPOINTS.reduce( // eslint-disable-next-line no-sequences function (propMap, breakpoint) { return propMap[suffixPropName(breakpoint, 'order')] = strNum(), propMap; }, create(null)); // For loop doesn't need to check hasOwnProperty // when using an object created from null var breakpointPropMap = assign(create(null), { col: keys(breakpointCol), offset: keys(breakpointOffset), order: keys(breakpointOrder) }); var props$j = assign({}, breakpointCol, breakpointOffset, breakpointOrder, { tag: { type: String, default: 'div' }, // Generic flexbox .col col: { type: Boolean, default: false }, // .col-[1-12]|auto cols: strNum(), // .offset-[1-12] offset: strNum(), // Flex ordering utility .order-[1-12] order: strNum(), alignSelf: { type: String, default: null, validator: function validator(str) { return arrayIncludes(['auto', 'start', 'end', 'center', 'baseline', 'stretch'], str); } } }); /** * We need ".col" to default in when no other props are passed, * but always render when col=true. */ var bCol = { functional: true, props: props$j, render: function render(h, _ref) { var _classList$push; var props = _ref.props, data = _ref.data, children = _ref.children; var classList = []; // Loop through `col`, `offset`, `order` breakpoint props for (var type in breakpointPropMap) { // Returns colSm, offset, offsetSm, orderMd, etc. var _keys = breakpointPropMap[type]; for (var i = 0; i < _keys.length; i++) { // computeBkPt(col, colSm => Sm, value=[String, Number, Boolean]) var c = computeBkPtClass(type, _keys[i].replace(type, ''), props[_keys[i]]); // If a class is returned, push it onto the array. if (c) { classList.push(c); } } } classList.push((_classList$push = { // Default to .col if no other classes generated nor `cols` specified. col: props.col || classList.length === 0 && !props.cols }, defineProperty(_classList$push, 'col-' + props.cols, props.cols), defineProperty(_classList$push, 'offset-' + props.offset, props.offset), defineProperty(_classList$push, 'order-' + props.order, props.order), defineProperty(_classList$push, 'align-self-' + props.alignSelf, props.alignSelf), _classList$push)); return h(props.tag, mergeData(data, { class: classList }), children); } }; var props$k = { tag: { type: String, default: 'div' } }; var bFormRow = { functional: true, props: props$k, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'form-row' }), children); } }; var components$9 = { bContainer: Container, bRow: bRow, bCol: bCol, bFormRow: bFormRow }; var VuePlugin$9 = { install: function install(Vue) { registerComponents(Vue, components$9); } }; vueUse(VuePlugin$9); /** * Issue #569: collapse::toggle::state triggered too many times * @link https://github.com/bootstrap-vue/bootstrap-vue/issues/569 */ var BVRL = '__BV_root_listeners__'; var listenOnRootMixin = { methods: { /** * Safely register event listeners on the root Vue node. * While Vue automatically removes listeners for individual components, * when a component registers a listener on root and is destroyed, * this orphans a callback because the node is gone, * but the root does not clear the callback. * * This adds a non-reactive prop to a vm on the fly * in order to avoid object observation and its performance costs * to something that needs no reactivity. * It should be highly unlikely there are any naming collisions. * @param {string} event * @param {function} callback * @chainable */ listenOnRoot: function listenOnRoot(event, callback) { if (!this[BVRL] || !isArray(this[BVRL])) { this[BVRL] = []; } this[BVRL].push({ event: event, callback: callback }); this.$root.$on(event, callback); return this; }, /** * Convenience method for calling vm.$emit on vm.$root. * @param {string} event * @param {*} args * @chainable */ emitOnRoot: function emitOnRoot(event) { var _$root; for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } (_$root = this.$root).$emit.apply(_$root, [event].concat(toConsumableArray(args))); return this; } }, beforeDestroy: function beforeDestroy() { if (this[BVRL] && isArray(this[BVRL])) { while (this[BVRL].length > 0) { // shift to process in order var _BVRL$shift = this[BVRL].shift(), event = _BVRL$shift.event, callback = _BVRL$shift.callback; this.$root.$off(event, callback); } } } }; // Events we emit on $root var EVENT_STATE = 'bv::collapse::state'; var EVENT_ACCORDION = 'bv::collapse::accordion'; // Events we listen to on $root var EVENT_TOGGLE = 'bv::toggle::collapse'; var bCollapse = { mixins: [listenOnRootMixin], render: function render(h) { var content = h(this.tag, { class: this.classObject, directives: [{ name: 'show', value: this.show }], attrs: { id: this.id || null }, on: { click: this.clickHandler } }, [this.$slots.default]); return h('transition', { props: { enterClass: '', enterActiveClass: 'collapsing', enterToClass: '', leaveClass: '', leaveActiveClass: 'collapsing', leaveToClass: '' }, on: { enter: this.onEnter, afterEnter: this.onAfterEnter, leave: this.onLeave, afterLeave: this.onAfterLeave } }, [content]); }, data: function data() { return { show: this.visible, transitioning: false }; }, model: { prop: 'visible', event: 'input' }, props: { id: { type: String, required: true }, isNav: { type: Boolean, default: false }, accordion: { type: String, default: null }, visible: { type: Boolean, default: false }, tag: { type: String, default: 'div' } }, watch: { visible: function visible(newVal) { if (newVal !== this.show) { this.show = newVal; } }, show: function show(newVal, oldVal) { if (newVal !== oldVal) { this.emitState(); } } }, computed: { classObject: function classObject() { return { 'navbar-collapse': this.isNav, 'collapse': !this.transitioning, 'show': this.show && !this.transitioning }; } }, methods: { toggle: function toggle() { this.show = !this.show; }, onEnter: function onEnter(el) { el.style.height = 0; reflow(el); el.style.height = el.scrollHeight + 'px'; this.transitioning = true; // This should be moved out so we can add cancellable events this.$emit('show'); }, onAfterEnter: function onAfterEnter(el) { el.style.height = null; this.transitioning = false; this.$emit('shown'); }, onLeave: function onLeave(el) { el.style.height = 'auto'; el.style.display = 'block'; el.style.height = el.getBoundingClientRect().height + 'px'; reflow(el); this.transitioning = true; el.style.height = 0; // This should be moved out so we can add cancellable events this.$emit('hide'); }, onAfterLeave: function onAfterLeave(el) { el.style.height = null; this.transitioning = false; this.$emit('hidden'); }, emitState: function emitState() { this.$emit('input', this.show); // Let v-b-toggle know the state of this collapse this.$root.$emit(EVENT_STATE, this.id, this.show); if (this.accordion && this.show) { // Tell the other collapses in this accordion to close this.$root.$emit(EVENT_ACCORDION, this.id, this.accordion); } }, clickHandler: function clickHandler(evt) { // If we are in a nav/navbar, close the collapse when non-disabled link clicked var el = evt.target; if (!this.isNav || !el || getComputedStyle(this.$el).display !== 'block') { return; } if (hasClass(el, 'nav-link') || hasClass(el, 'dropdown-item')) { this.show = false; } }, handleToggleEvt: function handleToggleEvt(target) { if (target !== this.id) { return; } this.toggle(); }, handleAccordionEvt: function handleAccordionEvt(openedId, accordion) { if (!this.accordion || accordion !== this.accordion) { return; } if (openedId === this.id) { // Open this collapse if not shown if (!this.show) { this.toggle(); } } else { // Close this collapse if shown if (this.show) { this.toggle(); } } }, handleResize: function handleResize() { // Handler for orientation/resize to set collapsed state in nav/navbar this.show = getComputedStyle(this.$el).display === 'block'; } }, created: function created() { // Listen for toggle events to open/close us this.listenOnRoot(EVENT_TOGGLE, this.handleToggleEvt); // Listen to otehr collapses for accordion events this.listenOnRoot(EVENT_ACCORDION, this.handleAccordionEvt); }, mounted: function mounted() { if (this.isNav && typeof document !== 'undefined') { // Set up handlers window.addEventListener('resize', this.handleResize, false); window.addEventListener('orientationchange', this.handleResize, false); this.handleResize(); } this.emitState(); }, beforeDestroy: function beforeDestroy() { if (this.isNav && typeof document !== 'undefined') { window.removeEventListener('resize', this.handleResize, false); window.removeEventListener('orientationchange', this.handleResize, false); } } }; var allListenTypes = { hover: true, click: true, focus: true }; var BVBoundListeners = '__BV_boundEventListeners__'; var bindTargets = function bindTargets(vnode, binding, listenTypes, fn) { var targets = keys(binding.modifiers || {}).filter(function (t) { return !allListenTypes[t]; }); if (binding.value) { targets.push(binding.value); } var listener = function listener() { fn({ targets: targets, vnode: vnode }); }; keys(allListenTypes).forEach(function (type) { if (listenTypes[type] || binding.modifiers[type]) { vnode.elm.addEventListener(type, listener); var boundListeners = vnode.elm[BVBoundListeners] || {}; boundListeners[type] = boundListeners[type] || []; boundListeners[type].push(listener); vnode.elm[BVBoundListeners] = boundListeners; } }); // Return the list of targets return targets; }; var unbindTargets = function unbindTargets(vnode, binding, listenTypes) { keys(allListenTypes).forEach(function (type) { if (listenTypes[type] || binding.modifiers[type]) { var boundListeners = vnode.elm[BVBoundListeners] && vnode.elm[BVBoundListeners][type]; if (boundListeners) { boundListeners.forEach(function (listener) { return vnode.elm.removeEventListener(type, listener); }); delete vnode.elm[BVBoundListeners][type]; } } }); }; // Are we client side? var inBrowser = typeof window !== 'undefined'; // target listen types var listenTypes = { click: true // Property key for handler storage };var BVT = '__BV_toggle__'; // Emitted Control Event for collapse (emitted to collapse) var EVENT_TOGGLE$1 = 'bv::toggle::collapse'; // Listen to Event for toggle state update (Emited by collapse) var EVENT_STATE$1 = 'bv::collapse::state'; var bToggle = { bind: function bind(el, binding, vnode) { var targets = bindTargets(vnode, binding, listenTypes, function (_ref) { var targets = _ref.targets, vnode = _ref.vnode; targets.forEach(function (target) { vnode.context.$root.$emit(EVENT_TOGGLE$1, target); }); }); if (inBrowser && vnode.context && targets.length > 0) { // Add aria attributes to element setAttr(el, 'aria-controls', targets.join(' ')); setAttr(el, 'aria-expanded', 'false'); if (el.tagName !== 'BUTTON') { // If element is not a button, we add `role="button"` for accessibility setAttr(el, 'role', 'button'); } // Toggle state hadnler, stored on element el[BVT] = function toggleDirectiveHandler(id, state) { if (targets.indexOf(id) !== -1) { // Set aria-expanded state setAttr(el, 'aria-expanded', state ? 'true' : 'false'); // Set/Clear 'collapsed' class state if (state) { removeClass(el, 'collapsed'); } else { addClass(el, 'collapsed'); } } }; // Listen for toggle state changes vnode.context.$root.$on(EVENT_STATE$1, el[BVT]); } }, unbind: function unbind(el, binding, vnode) { if (el[BVT]) { // Remove our $root listener vnode.context.$root.$off(EVENT_STATE$1, el[BVT]); el[BVT] = null; } } }; var directives = { bToggle: bToggle }; var VuePlugin$a = { install: function install(Vue) { registerDirectives(Vue, directives); } }; vueUse(VuePlugin$a); var components$a = { bCollapse: bCollapse }; var VuePlugin$b = { install: function install(Vue) { registerComponents(Vue, components$a); Vue.use(VuePlugin$a); } }; vueUse(VuePlugin$b); /**! * @fileOverview Kickass library to create and place poppers near their reference elements. * @version 1.14.3 * @license * Copyright (c) 2016 Federico Zivolo and contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; var timeoutDuration = 0; for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) { if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { timeoutDuration = 1; break; } } function microtaskDebounce(fn) { var called = false; return function () { if (called) { return; } called = true; window.Promise.resolve().then(function () { called = false; fn(); }); }; } function taskDebounce(fn) { var scheduled = false; return function () { if (!scheduled) { scheduled = true; setTimeout(function () { scheduled = false; fn(); }, timeoutDuration); } }; } var supportsMicroTasks = isBrowser && window.Promise; /** * Create a debounced version of a method, that's asynchronously deferred * but called in the minimum time possible. * * @method * @memberof Popper.Utils * @argument {Function} fn * @returns {Function} */ var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce; /** * Check if the given variable is a function * @method * @memberof Popper.Utils * @argument {Any} functionToCheck - variable to check * @returns {Boolean} answer to: is a function? */ function isFunction(functionToCheck) { var getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; } /** * Get CSS computed property of the given element * @method * @memberof Popper.Utils * @argument {Eement} element * @argument {String} property */ function getStyleComputedProperty(element, property) { if (element.nodeType !== 1) { return []; } // NOTE: 1 DOM access here var css = getComputedStyle(element, null); return property ? css[property] : css; } /** * Returns the parentNode or the host of the element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} parent */ function getParentNode(element) { if (element.nodeName === 'HTML') { return element; } return element.parentNode || element.host; } /** * Returns the scrolling parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} scroll parent */ function getScrollParent(element) { // Return body, `getScroll` will take care to get the correct `scrollTop` from it if (!element) { return document.body; } switch (element.nodeName) { case 'HTML': case 'BODY': return element.ownerDocument.body; case '#document': return element.body; } // Firefox want us to check `-x` and `-y` variations as well var _getStyleComputedProp = getStyleComputedProperty(element), overflow = _getStyleComputedProp.overflow, overflowX = _getStyleComputedProp.overflowX, overflowY = _getStyleComputedProp.overflowY; if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { return element; } return getScrollParent(getParentNode(element)); } var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); /** * Determines if the browser is Internet Explorer * @method * @memberof Popper.Utils * @param {Number} version to check * @returns {Boolean} isIE */ function isIE(version) { if (version === 11) { return isIE11; } if (version === 10) { return isIE10; } return isIE11 || isIE10; } /** * Returns the offset parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} offset parent */ function getOffsetParent(element) { if (!element) { return document.documentElement; } var noOffsetParent = isIE(10) ? document.body : null; // NOTE: 1 DOM access here var offsetParent = element.offsetParent; // Skip hidden elements which don't have an offsetParent while (offsetParent === noOffsetParent && element.nextElementSibling) { offsetParent = (element = element.nextElementSibling).offsetParent; } var nodeName = offsetParent && offsetParent.nodeName; if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { return element ? element.ownerDocument.documentElement : document.documentElement; } // .offsetParent will return the closest TD or TABLE in case // no offsetParent is present, I hate this job... if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') { return getOffsetParent(offsetParent); } return offsetParent; } function isOffsetContainer(element) { var nodeName = element.nodeName; if (nodeName === 'BODY') { return false; } return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element; } /** * Finds the root node (document, shadowDOM root) of the given element * @method * @memberof Popper.Utils * @argument {Element} node * @returns {Element} root node */ function getRoot(node) { if (node.parentNode !== null) { return getRoot(node.parentNode); } return node; } /** * Finds the offset parent common to the two provided nodes * @method * @memberof Popper.Utils * @argument {Element} element1 * @argument {Element} element2 * @returns {Element} common offset parent */ function findCommonOffsetParent(element1, element2) { // This check is needed to avoid errors in case one of the elements isn't defined for any reason if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { return document.documentElement; } // Here we make sure to give as "start" the element that comes first in the DOM var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING; var start = order ? element1 : element2; var end = order ? element2 : element1; // Get common ancestor container var range = document.createRange(); range.setStart(start, 0); range.setEnd(end, 0); var commonAncestorContainer = range.commonAncestorContainer; // Both nodes are inside #document if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) { if (isOffsetContainer(commonAncestorContainer)) { return commonAncestorContainer; } return getOffsetParent(commonAncestorContainer); } // one of the nodes is inside shadowDOM, find which one var element1root = getRoot(element1); if (element1root.host) { return findCommonOffsetParent(element1root.host, element2); } else { return findCommonOffsetParent(element1, getRoot(element2).host); } } /** * Gets the scroll value of the given element in the given side (top and left) * @method * @memberof Popper.Utils * @argument {Element} element * @argument {String} side `top` or `left` * @returns {number} amount of scrolled pixels */ function getScroll(element) { var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top'; var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; var nodeName = element.nodeName; if (nodeName === 'BODY' || nodeName === 'HTML') { var html = element.ownerDocument.documentElement; var scrollingElement = element.ownerDocument.scrollingElement || html; return scrollingElement[upperSide]; } return element[upperSide]; } /* * Sum or subtract the element scroll values (left and top) from a given rect object * @method * @memberof Popper.Utils * @param {Object} rect - Rect object you want to change * @param {HTMLElement} element - The element from the function reads the scroll values * @param {Boolean} subtract - set to true if you want to subtract the scroll values * @return {Object} rect - The modifier rect object */ function includeScroll(rect, element) { var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var scrollTop = getScroll(element, 'top'); var scrollLeft = getScroll(element, 'left'); var modifier = subtract ? -1 : 1; rect.top += scrollTop * modifier; rect.bottom += scrollTop * modifier; rect.left += scrollLeft * modifier; rect.right += scrollLeft * modifier; return rect; } /* * Helper to detect borders of a given element * @method * @memberof Popper.Utils * @param {CSSStyleDeclaration} styles * Result of `getStyleComputedProperty` on the given element * @param {String} axis - `x` or `y` * @return {number} borders - The borders size of the given axis */ function getBordersSize(styles, axis) { var sideA = axis === 'x' ? 'Left' : 'Top'; var sideB = sideA === 'Left' ? 'Right' : 'Bottom'; return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10); } function getSize(axis, body, html, computedStyle) { return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0); } function getWindowSizes() { var body = document.body; var html = document.documentElement; var computedStyle = isIE(10) && getComputedStyle(html); return { height: getSize('Height', body, html, computedStyle), width: getSize('Width', body, html, computedStyle) }; } var classCallCheck$1 = function classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass$1 = 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 defineProperty$2 = function defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends$1 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** * Given element offsets, generate an output similar to getBoundingClientRect * @method * @memberof Popper.Utils * @argument {Object} offsets * @returns {Object} ClientRect like output */ function getClientRect(offsets) { return _extends$1({}, offsets, { right: offsets.left + offsets.width, bottom: offsets.top + offsets.height }); } /** * Get bounding client rect of given element * @method * @memberof Popper.Utils * @param {HTMLElement} element * @return {Object} client rect */ function getBoundingClientRect(element) { var rect = {}; // IE10 10 FIX: Please, don't ask, the element isn't // considered in DOM in some circumstances... // This isn't reproducible in IE10 compatibility mode of IE11 try { if (isIE(10)) { rect = element.getBoundingClientRect(); var scrollTop = getScroll(element, 'top'); var scrollLeft = getScroll(element, 'left'); rect.top += scrollTop; rect.left += scrollLeft; rect.bottom += scrollTop; rect.right += scrollLeft; } else { rect = element.getBoundingClientRect(); } } catch (e) {} var result = { left: rect.left, top: rect.top, width: rect.right - rect.left, height: rect.bottom - rect.top }; // subtract scrollbar size from sizes var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {}; var width = sizes.width || element.clientWidth || result.right - result.left; var height = sizes.height || element.clientHeight || result.bottom - result.top; var horizScrollbar = element.offsetWidth - width; var vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border` // we make this check conditional for performance reasons if (horizScrollbar || vertScrollbar) { var styles = getStyleComputedProperty(element); horizScrollbar -= getBordersSize(styles, 'x'); vertScrollbar -= getBordersSize(styles, 'y'); result.width -= horizScrollbar; result.height -= vertScrollbar; } return getClientRect(result); } function getOffsetRectRelativeToArbitraryNode(children, parent) { var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var isIE10 = isIE(10); var isHTML = parent.nodeName === 'HTML'; var childrenRect = getBoundingClientRect(children); var parentRect = getBoundingClientRect(parent); var scrollParent = getScrollParent(children); var styles = getStyleComputedProperty(parent); var borderTopWidth = parseFloat(styles.borderTopWidth, 10); var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10); // In cases where the parent is fixed, we must ignore negative scroll in offset calc if (fixedPosition && parent.nodeName === 'HTML') { parentRect.top = Math.max(parentRect.top, 0); parentRect.left = Math.max(parentRect.left, 0); } var offsets = getClientRect({ top: childrenRect.top - parentRect.top - borderTopWidth, left: childrenRect.left - parentRect.left - borderLeftWidth, width: childrenRect.width, height: childrenRect.height }); offsets.marginTop = 0; offsets.marginLeft = 0; // Subtract margins of documentElement in case it's being used as parent // we do this only on HTML because it's the only element that behaves // differently when margins are applied to it. The margins are included in // the box of the documentElement, in the other cases not. if (!isIE10 && isHTML) { var marginTop = parseFloat(styles.marginTop, 10); var marginLeft = parseFloat(styles.marginLeft, 10); offsets.top -= borderTopWidth - marginTop; offsets.bottom -= borderTopWidth - marginTop; offsets.left -= borderLeftWidth - marginLeft; offsets.right -= borderLeftWidth - marginLeft; // Attach marginTop and marginLeft because in some circumstances we may need them offsets.marginTop = marginTop; offsets.marginLeft = marginLeft; } if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') { offsets = includeScroll(offsets, parent); } return offsets; } function getViewportOffsetRectRelativeToArtbitraryNode(element) { var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var html = element.ownerDocument.documentElement; var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); var width = Math.max(html.clientWidth, window.innerWidth || 0); var height = Math.max(html.clientHeight, window.innerHeight || 0); var scrollTop = !excludeScroll ? getScroll(html) : 0; var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; var offset = { top: scrollTop - relativeOffset.top + relativeOffset.marginTop, left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, width: width, height: height }; return getClientRect(offset); } /** * Check if the given element is fixed or is inside a fixed parent * @method * @memberof Popper.Utils * @argument {Element} element * @argument {Element} customContainer * @returns {Boolean} answer to "isFixed?" */ function isFixed(element) { var nodeName = element.nodeName; if (nodeName === 'BODY' || nodeName === 'HTML') { return false; } if (getStyleComputedProperty(element, 'position') === 'fixed') { return true; } return isFixed(getParentNode(element)); } /** * Finds the first parent of an element that has a transformed property defined * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} first transformed parent or documentElement */ function getFixedPositionOffsetParent(element) { // This check is needed to avoid errors in case one of the elements isn't defined for any reason if (!element || !element.parentElement || isIE()) { return document.documentElement; } var el = element.parentElement; while (el && getStyleComputedProperty(el, 'transform') === 'none') { el = el.parentElement; } return el || document.documentElement; } /** * Computed the boundaries limits and return them * @method * @memberof Popper.Utils * @param {HTMLElement} popper * @param {HTMLElement} reference * @param {number} padding * @param {HTMLElement} boundariesElement - Element used to define the boundaries * @param {Boolean} fixedPosition - Is in fixed position mode * @returns {Object} Coordinates of the boundaries */ function getBoundaries(popper, reference, padding, boundariesElement) { var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; // NOTE: 1 DOM access here var boundaries = { top: 0, left: 0 }; var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); // Handle viewport case if (boundariesElement === 'viewport') { boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition); } else { // Handle other cases based on DOM element used as boundaries var boundariesNode = void 0; if (boundariesElement === 'scrollParent') { boundariesNode = getScrollParent(getParentNode(reference)); if (boundariesNode.nodeName === 'BODY') { boundariesNode = popper.ownerDocument.documentElement; } } else if (boundariesElement === 'window') { boundariesNode = popper.ownerDocument.documentElement; } else { boundariesNode = boundariesElement; } var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition); // In case of HTML, we need a different computation if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { var _getWindowSizes = getWindowSizes(), height = _getWindowSizes.height, width = _getWindowSizes.width; boundaries.top += offsets.top - offsets.marginTop; boundaries.bottom = height + offsets.top; boundaries.left += offsets.left - offsets.marginLeft; boundaries.right = width + offsets.left; } else { // for all the other DOM elements, this one is good boundaries = offsets; } } // Add paddings boundaries.left += padding; boundaries.top += padding; boundaries.right -= padding; boundaries.bottom -= padding; return boundaries; } function getArea(_ref) { var width = _ref.width, height = _ref.height; return width * height; } /** * Utility used to transform the `auto` placement to the placement with more * available space. * @method * @memberof Popper.Utils * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) { var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; if (placement.indexOf('auto') === -1) { return placement; } var boundaries = getBoundaries(popper, reference, padding, boundariesElement); var rects = { top: { width: boundaries.width, height: refRect.top - boundaries.top }, right: { width: boundaries.right - refRect.right, height: boundaries.height }, bottom: { width: boundaries.width, height: boundaries.bottom - refRect.bottom }, left: { width: refRect.left - boundaries.left, height: boundaries.height } }; var sortedAreas = Object.keys(rects).map(function (key) { return _extends$1({ key: key }, rects[key], { area: getArea(rects[key]) }); }).sort(function (a, b) { return b.area - a.area; }); var filteredAreas = sortedAreas.filter(function (_ref2) { var width = _ref2.width, height = _ref2.height; return width >= popper.clientWidth && height >= popper.clientHeight; }); var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key; var variation = placement.split('-')[1]; return computedPlacement + (variation ? '-' + variation : ''); } /** * Get offsets to the reference element * @method * @memberof Popper.Utils * @param {Object} state * @param {Element} popper - the popper element * @param {Element} reference - the reference element (the popper will be relative to this) * @param {Element} fixedPosition - is in fixed position mode * @returns {Object} An object containing the offsets which will be applied to the popper */ function getReferenceOffsets(state, popper, reference) { var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); } /** * Get the outer sizes of the given element (offset size + margins) * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Object} object containing width and height properties */ function getOuterSizes(element) { var styles = getComputedStyle(element); var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom); var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight); var result = { width: element.offsetWidth + y, height: element.offsetHeight + x }; return result; } /** * Get the opposite placement of the given one * @method * @memberof Popper.Utils * @argument {String} placement * @returns {String} flipped placement */ function getOppositePlacement(placement) { var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; return placement.replace(/left|right|bottom|top/g, function (matched) { return hash[matched]; }); } /** * Get offsets to the popper * @method * @memberof Popper.Utils * @param {Object} position - CSS position the Popper will get applied * @param {HTMLElement} popper - the popper element * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) * @param {String} placement - one of the valid placement options * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper */ function getPopperOffsets(popper, referenceOffsets, placement) { placement = placement.split('-')[0]; // Get popper node sizes var popperRect = getOuterSizes(popper); // Add position, width and height to our offsets object var popperOffsets = { width: popperRect.width, height: popperRect.height }; // depending by the popper placement we have to compute its offsets slightly differently var isHoriz = ['right', 'left'].indexOf(placement) !== -1; var mainSide = isHoriz ? 'top' : 'left'; var secondarySide = isHoriz ? 'left' : 'top'; var measurement = isHoriz ? 'height' : 'width'; var secondaryMeasurement = !isHoriz ? 'height' : 'width'; popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2; if (placement === secondarySide) { popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; } else { popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)]; } return popperOffsets; } /** * Mimics the `find` method of Array * @method * @memberof Popper.Utils * @argument {Array} arr * @argument prop * @argument value * @returns index or -1 */ function find(arr, check) { // use native find if supported if (Array.prototype.find) { return arr.find(check); } // use `filter` to obtain the same behavior of `find` return arr.filter(check)[0]; } /** * Return the index of the matching object * @method * @memberof Popper.Utils * @argument {Array} arr * @argument prop * @argument value * @returns index or -1 */ function findIndex(arr, prop, value) { // use native findIndex if supported if (Array.prototype.findIndex) { return arr.findIndex(function (cur) { return cur[prop] === value; }); } // use `find` + `indexOf` if `findIndex` isn't supported var match = find(arr, function (obj) { return obj[prop] === value; }); return arr.indexOf(match); } /** * Loop trough the list of modifiers and run them in order, * each of them will then edit the data object. * @method * @memberof Popper.Utils * @param {dataObject} data * @param {Array} modifiers * @param {String} ends - Optional modifier name used as stopper * @returns {dataObject} */ function runModifiers(modifiers, data, ends) { var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends)); modifiersToRun.forEach(function (modifier) { if (modifier['function']) { // eslint-disable-line dot-notation console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); } var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation if (modifier.enabled && isFunction(fn)) { // Add properties to offsets to make them a complete clientRect object // we do this before each modifier to make sure the previous one doesn't // mess with these values data.offsets.popper = getClientRect(data.offsets.popper); data.offsets.reference = getClientRect(data.offsets.reference); data = fn(data, modifier); } }); return data; } /** * Updates the position of the popper, computing the new offsets and applying * the new style.
* Prefer `scheduleUpdate` over `update` because of performance reasons. * @method * @memberof Popper */ function update() { // if popper is destroyed, don't perform any further update if (this.state.isDestroyed) { return; } var data = { instance: this, styles: {}, arrowStyles: {}, attributes: {}, flipped: false, offsets: {} }; // compute reference element offsets data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed); // compute auto placement, store placement inside the data object, // modifiers will be able to edit `placement` if needed // and refer to originalPlacement to know the original value data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); // store the computed placement inside `originalPlacement` data.originalPlacement = data.placement; data.positionFixed = this.options.positionFixed; // compute the popper offsets data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute'; // run the modifiers data = runModifiers(this.modifiers, data); // the first `update` will call `onCreate` callback // the other ones will call `onUpdate` callback if (!this.state.isCreated) { this.state.isCreated = true; this.options.onCreate(data); } else { this.options.onUpdate(data); } } /** * Helper used to know if the given modifier is enabled. * @method * @memberof Popper.Utils * @returns {Boolean} */ function isModifierEnabled(modifiers, modifierName) { return modifiers.some(function (_ref) { var name = _ref.name, enabled = _ref.enabled; return enabled && name === modifierName; }); } /** * Get the prefixed supported property name * @method * @memberof Popper.Utils * @argument {String} property (camelCase) * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) */ function getSupportedPropertyName(property) { var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; var upperProp = property.charAt(0).toUpperCase() + property.slice(1); for (var i = 0; i < prefixes.length; i++) { var prefix = prefixes[i]; var toCheck = prefix ? '' + prefix + upperProp : property; if (typeof document.body.style[toCheck] !== 'undefined') { return toCheck; } } return null; } /** * Destroy the popper * @method * @memberof Popper */ function destroy() { this.state.isDestroyed = true; // touch DOM only if `applyStyle` modifier is enabled if (isModifierEnabled(this.modifiers, 'applyStyle')) { this.popper.removeAttribute('x-placement'); this.popper.style.position = ''; this.popper.style.top = ''; this.popper.style.left = ''; this.popper.style.right = ''; this.popper.style.bottom = ''; this.popper.style.willChange = ''; this.popper.style[getSupportedPropertyName('transform')] = ''; } this.disableEventListeners(); // remove the popper if user explicity asked for the deletion on destroy // do not use `remove` because IE11 doesn't support it if (this.options.removeOnDestroy) { this.popper.parentNode.removeChild(this.popper); } return this; } /** * Get the window associated with the element * @argument {Element} element * @returns {Window} */ function getWindow(element) { var ownerDocument = element.ownerDocument; return ownerDocument ? ownerDocument.defaultView : window; } function attachToScrollParents(scrollParent, event, callback, scrollParents) { var isBody = scrollParent.nodeName === 'BODY'; var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; target.addEventListener(event, callback, { passive: true }); if (!isBody) { attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); } scrollParents.push(target); } /** * Setup needed event listeners used to update the popper position * @method * @memberof Popper.Utils * @private */ function setupEventListeners(reference, options, state, updateBound) { // Resize event listener on window state.updateBound = updateBound; getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); // Scroll event listener on scroll parents var scrollElement = getScrollParent(reference); attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); state.scrollElement = scrollElement; state.eventsEnabled = true; return state; } /** * It will add resize/scroll events and start recalculating * position of the popper element when they are triggered. * @method * @memberof Popper */ function enableEventListeners() { if (!this.state.eventsEnabled) { this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); } } /** * Remove event listeners used to update the popper position * @method * @memberof Popper.Utils * @private */ function removeEventListeners(reference, state) { // Remove resize event listener on window getWindow(reference).removeEventListener('resize', state.updateBound); // Remove scroll event listener on scroll parents state.scrollParents.forEach(function (target) { target.removeEventListener('scroll', state.updateBound); }); // Reset state state.updateBound = null; state.scrollParents = []; state.scrollElement = null; state.eventsEnabled = false; return state; } /** * It will remove resize/scroll events and won't recalculate popper position * when they are triggered. It also won't trigger onUpdate callback anymore, * unless you call `update` method manually. * @method * @memberof Popper */ function disableEventListeners() { if (this.state.eventsEnabled) { cancelAnimationFrame(this.scheduleUpdate); this.state = removeEventListeners(this.reference, this.state); } } /** * Tells if a given input is a number * @method * @memberof Popper.Utils * @param {*} input to check * @return {Boolean} */ function isNumeric(n) { return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); } /** * Set the style to the given popper * @method * @memberof Popper.Utils * @argument {Element} element - Element to apply the style to * @argument {Object} styles * Object with a list of properties and values which will be applied to the element */ function setStyles(element, styles) { Object.keys(styles).forEach(function (prop) { var unit = ''; // add unit if the value is numeric and is one of the following if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { unit = 'px'; } element.style[prop] = styles[prop] + unit; }); } /** * Set the attributes to the given popper * @method * @memberof Popper.Utils * @argument {Element} element - Element to apply the attributes to * @argument {Object} styles * Object with a list of properties and values which will be applied to the element */ function setAttributes(element, attributes) { Object.keys(attributes).forEach(function (prop) { var value = attributes[prop]; if (value !== false) { element.setAttribute(prop, attributes[prop]); } else { element.removeAttribute(prop); } }); } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} data.styles - List of style properties - values to apply to popper element * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element * @argument {Object} options - Modifiers configuration and options * @returns {Object} The same data object */ function applyStyle(data) { // any property present in `data.styles` will be applied to the popper, // in this way we can make the 3rd party modifiers add custom styles to it // Be aware, modifiers could override the properties defined in the previous // lines of this modifier! setStyles(data.instance.popper, data.styles); // any property present in `data.attributes` will be applied to the popper, // they will be set as HTML attributes of the element setAttributes(data.instance.popper, data.attributes); // if arrowElement is defined and arrowStyles has some properties if (data.arrowElement && Object.keys(data.arrowStyles).length) { setStyles(data.arrowElement, data.arrowStyles); } return data; } /** * Set the x-placement attribute before everything else because it could be used * to add margins to the popper margins needs to be calculated to get the * correct popper offsets. * @method * @memberof Popper.modifiers * @param {HTMLElement} reference - The reference element used to position the popper * @param {HTMLElement} popper - The HTML element used as popper * @param {Object} options - Popper.js options */ function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { // compute reference element offsets var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); // compute auto placement, store placement inside the data object, // modifiers will be able to edit `placement` if needed // and refer to originalPlacement to know the original value var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); popper.setAttribute('x-placement', placement); // Apply `position` to popper before anything else because // without the position applied we can't guarantee correct computations setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' }); return options; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function computeStyle(data, options) { var x = options.x, y = options.y; var popper = data.offsets.popper; // Remove this legacy support in Popper.js v2 var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { return modifier.name === 'applyStyle'; }).gpuAcceleration; if (legacyGpuAccelerationOption !== undefined) { console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); } var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; var offsetParent = getOffsetParent(data.instance.popper); var offsetParentRect = getBoundingClientRect(offsetParent); // Styles var styles = { position: popper.position }; // Avoid blurry text by using full pixel integers. // For pixel-perfect positioning, top/bottom prefers rounded // values, while left/right prefers floored values. var offsets = { left: Math.floor(popper.left), top: Math.round(popper.top), bottom: Math.round(popper.bottom), right: Math.floor(popper.right) }; var sideA = x === 'bottom' ? 'top' : 'bottom'; var sideB = y === 'right' ? 'left' : 'right'; // if gpuAcceleration is set to `true` and transform is supported, // we use `translate3d` to apply the position to the popper we // automatically use the supported prefixed version if needed var prefixedProperty = getSupportedPropertyName('transform'); // now, let's make a step back and look at this code closely (wtf?) // If the content of the popper grows once it's been positioned, it // may happen that the popper gets misplaced because of the new content // overflowing its reference element // To avoid this problem, we provide two options (x and y), which allow // the consumer to define the offset origin. // If we position a popper on top of a reference element, we can set // `x` to `top` to make the popper grow towards its top instead of // its bottom. var left = void 0, top = void 0; if (sideA === 'bottom') { top = -offsetParentRect.height + offsets.bottom; } else { top = offsets.top; } if (sideB === 'right') { left = -offsetParentRect.width + offsets.right; } else { left = offsets.left; } if (gpuAcceleration && prefixedProperty) { styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; styles[sideA] = 0; styles[sideB] = 0; styles.willChange = 'transform'; } else { // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties var invertTop = sideA === 'bottom' ? -1 : 1; var invertLeft = sideB === 'right' ? -1 : 1; styles[sideA] = top * invertTop; styles[sideB] = left * invertLeft; styles.willChange = sideA + ', ' + sideB; } // Attributes var attributes = { 'x-placement': data.placement }; // Update `data` attributes, styles and arrowStyles data.attributes = _extends$1({}, attributes, data.attributes); data.styles = _extends$1({}, styles, data.styles); data.arrowStyles = _extends$1({}, data.offsets.arrow, data.arrowStyles); return data; } /** * Helper used to know if the given modifier depends from another one.
* It checks if the needed modifier is listed and enabled. * @method * @memberof Popper.Utils * @param {Array} modifiers - list of modifiers * @param {String} requestingName - name of requesting modifier * @param {String} requestedName - name of requested modifier * @returns {Boolean} */ function isModifierRequired(modifiers, requestingName, requestedName) { var requesting = find(modifiers, function (_ref) { var name = _ref.name; return name === requestingName; }); var isRequired = !!requesting && modifiers.some(function (modifier) { return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; }); if (!isRequired) { var _requesting = '`' + requestingName + '`'; var requested = '`' + requestedName + '`'; console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); } return isRequired; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function arrow(data, options) { var _data$offsets$arrow; // arrow depends on keepTogether in order to work if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { return data; } var arrowElement = options.element; // if arrowElement is a string, suppose it's a CSS selector if (typeof arrowElement === 'string') { arrowElement = data.instance.popper.querySelector(arrowElement); // if arrowElement is not found, don't run the modifier if (!arrowElement) { return data; } } else { // if the arrowElement isn't a query selector we must check that the // provided DOM node is child of its popper node if (!data.instance.popper.contains(arrowElement)) { console.warn('WARNING: `arrow.element` must be child of its popper element!'); return data; } } var placement = data.placement.split('-')[0]; var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var isVertical = ['left', 'right'].indexOf(placement) !== -1; var len = isVertical ? 'height' : 'width'; var sideCapitalized = isVertical ? 'Top' : 'Left'; var side = sideCapitalized.toLowerCase(); var altSide = isVertical ? 'left' : 'top'; var opSide = isVertical ? 'bottom' : 'right'; var arrowElementSize = getOuterSizes(arrowElement)[len]; // // extends keepTogether behavior making sure the popper and its // reference have enough pixels in conjuction // // top/left side if (reference[opSide] - arrowElementSize < popper[side]) { data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); } // bottom/right side if (reference[side] + arrowElementSize > popper[opSide]) { data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; } data.offsets.popper = getClientRect(data.offsets.popper); // compute center of the popper var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; // Compute the sideValue using the updated popper offsets // take popper margin in account because we don't have this info available var css = getStyleComputedProperty(data.instance.popper); var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10); var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10); var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; // prevent arrowElement from being placed not contiguously to its popper sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); data.arrowElement = arrowElement; data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty$2(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty$2(_data$offsets$arrow, altSide, ''), _data$offsets$arrow); return data; } /** * Get the opposite placement variation of the given one * @method * @memberof Popper.Utils * @argument {String} placement variation * @returns {String} flipped placement variation */ function getOppositeVariation(variation) { if (variation === 'end') { return 'start'; } else if (variation === 'start') { return 'end'; } return variation; } /** * List of accepted placements to use as values of the `placement` option.
* Valid placements are: * - `auto` * - `top` * - `right` * - `bottom` * - `left` * * Each placement can have a variation from this list: * - `-start` * - `-end` * * Variations are interpreted easily if you think of them as the left to right * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` * is right.
* Vertically (`left` and `right`), `start` is top and `end` is bottom. * * Some valid examples are: * - `top-end` (on top of reference, right aligned) * - `right-start` (on right of reference, top aligned) * - `bottom` (on bottom, centered) * - `auto-right` (on the side with more space available, alignment depends by placement) * * @static * @type {Array} * @enum {String} * @readonly * @method placements * @memberof Popper */ var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; // Get rid of `auto` `auto-start` and `auto-end` var validPlacements = placements.slice(3); /** * Given an initial placement, returns all the subsequent placements * clockwise (or counter-clockwise). * * @method * @memberof Popper.Utils * @argument {String} placement - A valid placement (it accepts variations) * @argument {Boolean} counter - Set to true to walk the placements counterclockwise * @returns {Array} placements including their variations */ function clockwise(placement) { var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var index = validPlacements.indexOf(placement); var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); return counter ? arr.reverse() : arr; } var BEHAVIORS = { FLIP: 'flip', CLOCKWISE: 'clockwise', COUNTERCLOCKWISE: 'counterclockwise' }; /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function flip(data, options) { // if `inner` modifier is enabled, we can't use the `flip` modifier if (isModifierEnabled(data.instance.modifiers, 'inner')) { return data; } if (data.flipped && data.placement === data.originalPlacement) { // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides return data; } var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed); var placement = data.placement.split('-')[0]; var placementOpposite = getOppositePlacement(placement); var variation = data.placement.split('-')[1] || ''; var flipOrder = []; switch (options.behavior) { case BEHAVIORS.FLIP: flipOrder = [placement, placementOpposite]; break; case BEHAVIORS.CLOCKWISE: flipOrder = clockwise(placement); break; case BEHAVIORS.COUNTERCLOCKWISE: flipOrder = clockwise(placement, true); break; default: flipOrder = options.behavior; } flipOrder.forEach(function (step, index) { if (placement !== step || flipOrder.length === index + 1) { return data; } placement = data.placement.split('-')[0]; placementOpposite = getOppositePlacement(placement); var popperOffsets = data.offsets.popper; var refOffsets = data.offsets.reference; // using floor because the reference offsets may contain decimals we are not going to consider here var floor = Math.floor; var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom); var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; // flip the variation if required var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); if (overlapsRef || overflowsBoundaries || flippedVariation) { // this boolean to detect any flip loop data.flipped = true; if (overlapsRef || overflowsBoundaries) { placement = flipOrder[index + 1]; } if (flippedVariation) { variation = getOppositeVariation(variation); } data.placement = placement + (variation ? '-' + variation : ''); // this object contains `position`, we want to preserve it along with // any additional property we may add in the future data.offsets.popper = _extends$1({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); data = runModifiers(data.instance.modifiers, data, 'flip'); } }); return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function keepTogether(data) { var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var placement = data.placement.split('-')[0]; var floor = Math.floor; var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; var side = isVertical ? 'right' : 'bottom'; var opSide = isVertical ? 'left' : 'top'; var measurement = isVertical ? 'width' : 'height'; if (popper[side] < floor(reference[opSide])) { data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; } if (popper[opSide] > floor(reference[side])) { data.offsets.popper[opSide] = floor(reference[side]); } return data; } /** * Converts a string containing value + unit into a px value number * @function * @memberof {modifiers~offset} * @private * @argument {String} str - Value + unit string * @argument {String} measurement - `height` or `width` * @argument {Object} popperOffsets * @argument {Object} referenceOffsets * @returns {Number|String} * Value in pixels, or original string if no values were extracted */ function toValue(str, measurement, popperOffsets, referenceOffsets) { // separate value from unit var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); var value = +split[1]; var unit = split[2]; // If it's not a number it's an operator, I guess if (!value) { return str; } if (unit.indexOf('%') === 0) { var element = void 0; switch (unit) { case '%p': element = popperOffsets; break; case '%': case '%r': default: element = referenceOffsets; } var rect = getClientRect(element); return rect[measurement] / 100 * value; } else if (unit === 'vh' || unit === 'vw') { // if is a vh or vw, we calculate the size based on the viewport var size = void 0; if (unit === 'vh') { size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); } else { size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); } return size / 100 * value; } else { // if is an explicit pixel unit, we get rid of the unit and keep the value // if is an implicit unit, it's px, and we return just the value return value; } } /** * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. * @function * @memberof {modifiers~offset} * @private * @argument {String} offset * @argument {Object} popperOffsets * @argument {Object} referenceOffsets * @argument {String} basePlacement * @returns {Array} a two cells array with x and y offsets in numbers */ function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { var offsets = [0, 0]; // Use height if placement is left or right and index is 0 otherwise use width // in this way the first offset will use an axis and the second one // will use the other one var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; // Split the offset string to obtain a list of values and operands // The regex addresses values with the plus or minus sign in front (+10, -20, etc) var fragments = offset.split(/(\+|\-)/).map(function (frag) { return frag.trim(); }); // Detect if the offset string contains a pair of values or a single one // they could be separated by comma or space var divider = fragments.indexOf(find(fragments, function (frag) { return frag.search(/,|\s/) !== -1; })); if (fragments[divider] && fragments[divider].indexOf(',') === -1) { console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); } // If divider is found, we divide the list of values and operands to divide // them by ofset X and Y. var splitRegex = /\s*,\s*|\s+/; var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; // Convert the values with units to absolute pixels to allow our computations ops = ops.map(function (op, index) { // Most of the units rely on the orientation of the popper var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; var mergeWithPrevious = false; return op // This aggregates any `+` or `-` sign that aren't considered operators // e.g.: 10 + +5 => [10, +, +5] .reduce(function (a, b) { if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { a[a.length - 1] = b; mergeWithPrevious = true; return a; } else if (mergeWithPrevious) { a[a.length - 1] += b; mergeWithPrevious = false; return a; } else { return a.concat(b); } }, []) // Here we convert the string values into number values (in px) .map(function (str) { return toValue(str, measurement, popperOffsets, referenceOffsets); }); }); // Loop trough the offsets arrays and execute the operations ops.forEach(function (op, index) { op.forEach(function (frag, index2) { if (isNumeric(frag)) { offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); } }); }); return offsets; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @argument {Number|String} options.offset=0 * The offset value as described in the modifier description * @returns {Object} The data object, properly modified */ function offset$1(data, _ref) { var offset = _ref.offset; var placement = data.placement, _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var basePlacement = placement.split('-')[0]; var offsets = void 0; if (isNumeric(+offset)) { offsets = [+offset, 0]; } else { offsets = parseOffset(offset, popper, reference, basePlacement); } if (basePlacement === 'left') { popper.top += offsets[0]; popper.left -= offsets[1]; } else if (basePlacement === 'right') { popper.top += offsets[0]; popper.left += offsets[1]; } else if (basePlacement === 'top') { popper.left += offsets[0]; popper.top -= offsets[1]; } else if (basePlacement === 'bottom') { popper.left += offsets[0]; popper.top += offsets[1]; } data.popper = popper; return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function preventOverflow(data, options) { var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); // If offsetParent is the reference element, we really want to // go one step up and use the next offsetParent as reference to // avoid to make this modifier completely useless and look like broken if (data.instance.reference === boundariesElement) { boundariesElement = getOffsetParent(boundariesElement); } // NOTE: DOM access here // resets the popper's position so that the document size can be calculated excluding // the size of the popper element itself var transformProp = getSupportedPropertyName('transform'); var popperStyles = data.instance.popper.style; // assignment to help minification var top = popperStyles.top, left = popperStyles.left, transform = popperStyles[transformProp]; popperStyles.top = ''; popperStyles.left = ''; popperStyles[transformProp] = ''; var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed); // NOTE: DOM access here // restores the original style properties after the offsets have been computed popperStyles.top = top; popperStyles.left = left; popperStyles[transformProp] = transform; options.boundaries = boundaries; var order = options.priority; var popper = data.offsets.popper; var check = { primary: function primary(placement) { var value = popper[placement]; if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { value = Math.max(popper[placement], boundaries[placement]); } return defineProperty$2({}, placement, value); }, secondary: function secondary(placement) { var mainSide = placement === 'right' ? 'left' : 'top'; var value = popper[mainSide]; if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); } return defineProperty$2({}, mainSide, value); } }; order.forEach(function (placement) { var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; popper = _extends$1({}, popper, check[side](placement)); }); data.offsets.popper = popper; return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function shift(data) { var placement = data.placement; var basePlacement = placement.split('-')[0]; var shiftvariation = placement.split('-')[1]; // if shift shiftvariation is specified, run the modifier if (shiftvariation) { var _data$offsets = data.offsets, reference = _data$offsets.reference, popper = _data$offsets.popper; var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; var side = isVertical ? 'left' : 'top'; var measurement = isVertical ? 'width' : 'height'; var shiftOffsets = { start: defineProperty$2({}, side, reference[side]), end: defineProperty$2({}, side, reference[side] + reference[measurement] - popper[measurement]) }; data.offsets.popper = _extends$1({}, popper, shiftOffsets[shiftvariation]); } return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by update method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function hide(data) { if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { return data; } var refRect = data.offsets.reference; var bound = find(data.instance.modifiers, function (modifier) { return modifier.name === 'preventOverflow'; }).boundaries; if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { // Avoid unnecessary DOM access if visibility hasn't changed if (data.hide === true) { return data; } data.hide = true; data.attributes['x-out-of-boundaries'] = ''; } else { // Avoid unnecessary DOM access if visibility hasn't changed if (data.hide === false) { return data; } data.hide = false; data.attributes['x-out-of-boundaries'] = false; } return data; } /** * @function * @memberof Modifiers * @argument {Object} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {Object} The data object, properly modified */ function inner(data) { var placement = data.placement; var basePlacement = placement.split('-')[0]; var _data$offsets = data.offsets, popper = _data$offsets.popper, reference = _data$offsets.reference; var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); data.placement = getOppositePlacement(placement); data.offsets.popper = getClientRect(popper); return data; } /** * Modifier function, each modifier can have a function of this type assigned * to its `fn` property.
* These functions will be called on each update, this means that you must * make sure they are performant enough to avoid performance bottlenecks. * * @function ModifierFn * @argument {dataObject} data - The data object generated by `update` method * @argument {Object} options - Modifiers configuration and options * @returns {dataObject} The data object, properly modified */ /** * Modifiers are plugins used to alter the behavior of your poppers.
* Popper.js uses a set of 9 modifiers to provide all the basic functionalities * needed by the library. * * Usually you don't want to override the `order`, `fn` and `onLoad` props. * All the other properties are configurations that could be tweaked. * @namespace modifiers */ var modifiers = { /** * Modifier used to shift the popper on the start or end of its reference * element.
* It will read the variation of the `placement` property.
* It can be one either `-end` or `-start`. * @memberof modifiers * @inner */ shift: { /** @prop {number} order=100 - Index used to define the order of execution */ order: 100, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: shift }, /** * The `offset` modifier can shift your popper on both its axis. * * It accepts the following units: * - `px` or unitless, interpreted as pixels * - `%` or `%r`, percentage relative to the length of the reference element * - `%p`, percentage relative to the length of the popper element * - `vw`, CSS viewport width unit * - `vh`, CSS viewport height unit * * For length is intended the main axis relative to the placement of the popper.
* This means that if the placement is `top` or `bottom`, the length will be the * `width`. In case of `left` or `right`, it will be the height. * * You can provide a single value (as `Number` or `String`), or a pair of values * as `String` divided by a comma or one (or more) white spaces.
* The latter is a deprecated method because it leads to confusion and will be * removed in v2.
* Additionally, it accepts additions and subtractions between different units. * Note that multiplications and divisions aren't supported. * * Valid examples are: * ``` * 10 * '10%' * '10, 10' * '10%, 10' * '10 + 10%' * '10 - 5vh + 3%' * '-10px + 5vh, 5px - 6%' * ``` * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap * > with their reference element, unfortunately, you will have to disable the `flip` modifier. * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373) * * @memberof modifiers * @inner */ offset: { /** @prop {number} order=200 - Index used to define the order of execution */ order: 200, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: offset$1, /** @prop {Number|String} offset=0 * The offset value as described in the modifier description */ offset: 0 }, /** * Modifier used to prevent the popper from being positioned outside the boundary. * * An scenario exists where the reference itself is not within the boundaries.
* We can say it has "escaped the boundaries" — or just "escaped".
* In this case we need to decide whether the popper should either: * * - detach from the reference and remain "trapped" in the boundaries, or * - if it should ignore the boundary and "escape with its reference" * * When `escapeWithReference` is set to`true` and reference is completely * outside its boundaries, the popper will overflow (or completely leave) * the boundaries in order to remain attached to the edge of the reference. * * @memberof modifiers * @inner */ preventOverflow: { /** @prop {number} order=300 - Index used to define the order of execution */ order: 300, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: preventOverflow, /** * @prop {Array} [priority=['left','right','top','bottom']] * Popper will try to prevent overflow following these priorities by default, * then, it could overflow on the left and on top of the `boundariesElement` */ priority: ['left', 'right', 'top', 'bottom'], /** * @prop {number} padding=5 * Amount of pixel used to define a minimum distance between the boundaries * and the popper this makes sure the popper has always a little padding * between the edges of its container */ padding: 5, /** * @prop {String|HTMLElement} boundariesElement='scrollParent' * Boundaries used by the modifier, can be `scrollParent`, `window`, * `viewport` or any DOM element. */ boundariesElement: 'scrollParent' }, /** * Modifier used to make sure the reference and its popper stay near eachothers * without leaving any gap between the two. Expecially useful when the arrow is * enabled and you want to assure it to point to its reference element. * It cares only about the first axis, you can still have poppers with margin * between the popper and its reference element. * @memberof modifiers * @inner */ keepTogether: { /** @prop {number} order=400 - Index used to define the order of execution */ order: 400, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: keepTogether }, /** * This modifier is used to move the `arrowElement` of the popper to make * sure it is positioned between the reference element and its popper element. * It will read the outer size of the `arrowElement` node to detect how many * pixels of conjuction are needed. * * It has no effect if no `arrowElement` is provided. * @memberof modifiers * @inner */ arrow: { /** @prop {number} order=500 - Index used to define the order of execution */ order: 500, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: arrow, /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ element: '[x-arrow]' }, /** * Modifier used to flip the popper's placement when it starts to overlap its * reference element. * * Requires the `preventOverflow` modifier before it in order to work. * * **NOTE:** this modifier will interrupt the current update cycle and will * restart it if it detects the need to flip the placement. * @memberof modifiers * @inner */ flip: { /** @prop {number} order=600 - Index used to define the order of execution */ order: 600, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: flip, /** * @prop {String|Array} behavior='flip' * The behavior used to change the popper's placement. It can be one of * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid * placements (with optional variations). */ behavior: 'flip', /** * @prop {number} padding=5 * The popper will flip if it hits the edges of the `boundariesElement` */ padding: 5, /** * @prop {String|HTMLElement} boundariesElement='viewport' * The element which will define the boundaries of the popper position, * the popper will never be placed outside of the defined boundaries * (except if keepTogether is enabled) */ boundariesElement: 'viewport' }, /** * Modifier used to make the popper flow toward the inner of the reference element. * By default, when this modifier is disabled, the popper will be placed outside * the reference element. * @memberof modifiers * @inner */ inner: { /** @prop {number} order=700 - Index used to define the order of execution */ order: 700, /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ enabled: false, /** @prop {ModifierFn} */ fn: inner }, /** * Modifier used to hide the popper when its reference element is outside of the * popper boundaries. It will set a `x-out-of-boundaries` attribute which can * be used to hide with a CSS selector the popper when its reference is * out of boundaries. * * Requires the `preventOverflow` modifier before it in order to work. * @memberof modifiers * @inner */ hide: { /** @prop {number} order=800 - Index used to define the order of execution */ order: 800, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: hide }, /** * Computes the style that will be applied to the popper element to gets * properly positioned. * * Note that this modifier will not touch the DOM, it just prepares the styles * so that `applyStyle` modifier can apply it. This separation is useful * in case you need to replace `applyStyle` with a custom implementation. * * This modifier has `850` as `order` value to maintain backward compatibility * with previous versions of Popper.js. Expect the modifiers ordering method * to change in future major versions of the library. * * @memberof modifiers * @inner */ computeStyle: { /** @prop {number} order=850 - Index used to define the order of execution */ order: 850, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: computeStyle, /** * @prop {Boolean} gpuAcceleration=true * If true, it uses the CSS 3d transformation to position the popper. * Otherwise, it will use the `top` and `left` properties. */ gpuAcceleration: true, /** * @prop {string} [x='bottom'] * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. * Change this if your popper should grow in a direction different from `bottom` */ x: 'bottom', /** * @prop {string} [x='left'] * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. * Change this if your popper should grow in a direction different from `right` */ y: 'right' }, /** * Applies the computed styles to the popper element. * * All the DOM manipulations are limited to this modifier. This is useful in case * you want to integrate Popper.js inside a framework or view library and you * want to delegate all the DOM manipulations to it. * * Note that if you disable this modifier, you must make sure the popper element * has its position set to `absolute` before Popper.js can do its work! * * Just disable this modifier and define you own to achieve the desired effect. * * @memberof modifiers * @inner */ applyStyle: { /** @prop {number} order=900 - Index used to define the order of execution */ order: 900, /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ enabled: true, /** @prop {ModifierFn} */ fn: applyStyle, /** @prop {Function} */ onLoad: applyStyleOnLoad, /** * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier * @prop {Boolean} gpuAcceleration=true * If true, it uses the CSS 3d transformation to position the popper. * Otherwise, it will use the `top` and `left` properties. */ gpuAcceleration: undefined } }; /** * The `dataObject` is an object containing all the informations used by Popper.js * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks. * @name dataObject * @property {Object} data.instance The Popper.js instance * @property {String} data.placement Placement applied to popper * @property {String} data.originalPlacement Placement originally defined on init * @property {Boolean} data.flipped True if popper has been flipped by flip modifier * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper. * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`) * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`) * @property {Object} data.boundaries Offsets of the popper boundaries * @property {Object} data.offsets The measurements of popper, reference and arrow elements. * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 */ /** * Default options provided to Popper.js constructor.
* These can be overriden using the `options` argument of Popper.js.
* To override an option, simply pass as 3rd argument an object with the same * structure of this object, example: * ``` * new Popper(ref, pop, { * modifiers: { * preventOverflow: { enabled: false } * } * }) * ``` * @type {Object} * @static * @memberof Popper */ var Defaults = { /** * Popper's placement * @prop {Popper.placements} placement='bottom' */ placement: 'bottom', /** * Set this to true if you want popper to position it self in 'fixed' mode * @prop {Boolean} positionFixed=false */ positionFixed: false, /** * Whether events (resize, scroll) are initially enabled * @prop {Boolean} eventsEnabled=true */ eventsEnabled: true, /** * Set to true if you want to automatically remove the popper when * you call the `destroy` method. * @prop {Boolean} removeOnDestroy=false */ removeOnDestroy: false, /** * Callback called when the popper is created.
* By default, is set to no-op.
* Access Popper.js instance with `data.instance`. * @prop {onCreate} */ onCreate: function onCreate() {}, /** * Callback called when the popper is updated, this callback is not called * on the initialization/creation of the popper, but only on subsequent * updates.
* By default, is set to no-op.
* Access Popper.js instance with `data.instance`. * @prop {onUpdate} */ onUpdate: function onUpdate() {}, /** * List of modifiers used to modify the offsets before they are applied to the popper. * They provide most of the functionalities of Popper.js * @prop {modifiers} */ modifiers: modifiers }; /** * @callback onCreate * @param {dataObject} data */ /** * @callback onUpdate * @param {dataObject} data */ // Utils // Methods var Popper = function () { /** * Create a new Popper.js instance * @class Popper * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper * @param {HTMLElement} popper - The HTML element used as popper. * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) * @return {Object} instance - The generated Popper.js instance */ function Popper(reference, popper) { var _this = this; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; classCallCheck$1(this, Popper); this.scheduleUpdate = function () { return requestAnimationFrame(_this.update); }; // make update() debounced, so that it only runs at most once-per-tick this.update = debounce(this.update.bind(this)); // with {} we create a new object with the options inside it this.options = _extends$1({}, Popper.Defaults, options); // init state this.state = { isDestroyed: false, isCreated: false, scrollParents: [] }; // get reference and popper elements (allow jQuery wrappers) this.reference = reference && reference.jquery ? reference[0] : reference; this.popper = popper && popper.jquery ? popper[0] : popper; // Deep merge modifiers options this.options.modifiers = {}; Object.keys(_extends$1({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { _this.options.modifiers[name] = _extends$1({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); }); // Refactoring modifiers' list (Object => Array) this.modifiers = Object.keys(this.options.modifiers).map(function (name) { return _extends$1({ name: name }, _this.options.modifiers[name]); }) // sort the modifiers by order .sort(function (a, b) { return a.order - b.order; }); // modifiers have the ability to execute arbitrary code when Popper.js get inited // such code is executed in the same order of its modifier // they could add new properties to their options configuration // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! this.modifiers.forEach(function (modifierOptions) { if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); } }); // fire the first update to position the popper in the right place this.update(); var eventsEnabled = this.options.eventsEnabled; if (eventsEnabled) { // setup event listeners, they will take care of update the position in specific situations this.enableEventListeners(); } this.state.eventsEnabled = eventsEnabled; } // We can't use class properties because they don't get listed in the // class prototype and break stuff like Sinon stubs createClass$1(Popper, [{ key: 'update', value: function update$$1() { return update.call(this); } }, { key: 'destroy', value: function destroy$$1() { return destroy.call(this); } }, { key: 'enableEventListeners', value: function enableEventListeners$$1() { return enableEventListeners.call(this); } }, { key: 'disableEventListeners', value: function disableEventListeners$$1() { return disableEventListeners.call(this); } /** * Schedule an update, it will run on the next UI update available * @method scheduleUpdate * @memberof Popper */ /** * Collection of utilities useful when writing custom modifiers. * Starting from version 1.7, this method is available only if you * include `popper-utils.js` before `popper.js`. * * **DEPRECATION**: This way to access PopperUtils is deprecated * and will be removed in v2! Use the PopperUtils module directly instead. * Due to the high instability of the methods contained in Utils, we can't * guarantee them to follow semver. Use them at your own risk! * @static * @private * @type {Object} * @deprecated since version 1.8 * @member Utils * @memberof Popper */ }]); return Popper; }(); /** * The `referenceObject` is an object that provides an interface compatible with Popper.js * and lets you use it as replacement of a real DOM node.
* You can use this method to position a popper relatively to a set of coordinates * in case you don't have a DOM node to use as reference. * * ``` * new Popper(referenceObject, popperNode); * ``` * * NB: This feature isn't supported in Internet Explorer 10 * @name referenceObject * @property {Function} data.getBoundingClientRect * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. * @property {number} data.clientWidth * An ES6 getter that will return the width of the virtual reference element. * @property {number} data.clientHeight * An ES6 getter that will return the height of the virtual reference element. */ Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; Popper.placements = placements; Popper.Defaults = Defaults; var clickoutMixin = { mounted: function mounted() { if (typeof document !== 'undefined') { document.documentElement.addEventListener('click', this._clickOutListener); } }, beforeDestroy: function beforeDestroy() { if (typeof document !== 'undefined') { document.documentElement.removeEventListener('click', this._clickOutListener); } }, methods: { _clickOutListener: function _clickOutListener(e) { if (!this.$el.contains(e.target)) { if (this.clickOutListener) { this.clickOutListener(); } } } } }; var BvEvent = function () { function BvEvent(type) { var eventInit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; classCallCheck(this, BvEvent); // Start by emulating native Event constructor. if (!type) { throw new TypeError('Failed to construct \'' + this.constructor.name + '\'. 1 argument required, ' + arguments.length + ' given.'); } // Assign defaults first, the eventInit, // and the type last so it can't be overwritten. assign(this, BvEvent.defaults(), eventInit, { type: type }); // Freeze some props as readonly, but leave them enumerable. defineProperties(this, { type: readonlyDescriptor(), cancelable: readonlyDescriptor(), nativeEvent: readonlyDescriptor(), target: readonlyDescriptor(), relatedTarget: readonlyDescriptor(), vueTarget: readonlyDescriptor() }); // Create a private variable using closure scoping. var defaultPrevented = false; // Recreate preventDefault method. One way setter. this.preventDefault = function preventDefault() { if (this.cancelable) { defaultPrevented = true; } }; // Create 'defaultPrevented' publicly accessible prop // that can only be altered by the preventDefault method. defineProperty$1(this, 'defaultPrevented', { enumerable: true, get: function get$$1() { return defaultPrevented; } }); } createClass(BvEvent, null, [{ key: 'defaults', value: function defaults$$1() { return { type: '', cancelable: true, nativeEvent: null, target: null, relatedTarget: null, vueTarget: null }; } }]); return BvEvent; }(); // Return an Array of visible items function filterVisible(els) { return (els || []).filter(isVisible); } // Dropdown item CSS selectors // TODO: .dropdown-form handling var ITEM_SELECTOR$1 = '.dropdown-item:not(.disabled):not([disabled])'; // Popper attachment positions var AttachmentMap = { // DropUp Left Align TOP: 'top-start', // DropUp Right Align TOPEND: 'top-end', // Dropdown left Align BOTTOM: 'bottom-start', // Dropdown Right Align BOTTOMEND: 'bottom-end' }; var dropdownMixin = { mixins: [clickoutMixin, listenOnRootMixin], props: { disabled: { type: Boolean, default: false }, text: { // Button label type: String, default: '' }, dropup: { // place on top if possible type: Boolean, default: false }, right: { // Right align menu (default is left align) type: Boolean, default: false }, offset: { // Number of pixels to offset menu, or a CSS unit value (i.e. 1px, 1rem, etc) type: [Number, String], default: 0 }, noFlip: { // Disable auto-flipping of menu from bottom<=>top type: Boolean, default: false }, popperOpts: { type: Object, default: function _default() {} } }, data: function data() { return { visible: false, inNavbar: null, visibleChangePrevented: false }; }, created: function created() { // Create non-reactive property this._popper = null; }, mounted: function mounted() { // To keep one dropdown opened on page this.listenOnRoot('bv::dropdown::shown', this.rootCloseListener); // Hide when clicked on links this.listenOnRoot('clicked::link', this.rootCloseListener); // Use new namespaced events this.listenOnRoot('bv::link::clicked', this.rootCloseListener); }, /* istanbul ignore next: not easy to test */ deactivated: function deactivated() { // In case we are inside a `` this.visible = false; this.setTouchStart(false); this.removePopper(); }, /* istanbul ignore next: not easy to test */ beforeDestroy: function beforeDestroy() { this.visible = false; this.setTouchStart(false); this.removePopper(); }, watch: { visible: function visible(newValue, oldValue) { if (this.visibleChangePrevented) { this.visibleChangePrevented = false; return; } if (newValue !== oldValue) { var evtName = newValue ? 'show' : 'hide'; var bvEvt = new BvEvent(evtName, { cancelable: true, vueTarget: this, target: this.$refs.menu, relatedTarget: null }); this.emitEvent(bvEvt); if (bvEvt.defaultPrevented) { // Reset value and exit if canceled this.visibleChangePrevented = true; this.visible = oldValue; return; } if (evtName === 'show') { this.showMenu(); } else { this.hideMenu(); } } }, disabled: function disabled(newValue, oldValue) { if (newValue !== oldValue && newValue && this.visible) { // Hide dropdown if disabled changes to true this.visible = false; } } }, computed: { toggler: function toggler() { return this.$refs.toggle.$el || this.$refs.toggle; } }, methods: { // Event emitter emitEvent: function emitEvent(bvEvt) { var type = bvEvt.type; this.$emit(type, bvEvt); this.emitOnRoot('bv::dropdown::' + type, bvEvt); }, showMenu: function showMenu() { if (this.disabled) { return; } // Ensure other menus are closed this.emitOnRoot('bv::dropdown::shown', this); // Are we in a navbar ? if (this.inNavbar === null && this.isNav) { this.inNavbar = Boolean(closest('.navbar', this.$el)); } // Disable totally Popper.js for Dropdown in Navbar /* istnbul ignore next: can't test popper in JSDOM */ if (!this.inNavbar) { if (typeof Popper === 'undefined') { warn('b-dropdown: Popper.js not found. Falling back to CSS positioning.'); } else { // for dropup with alignment we use the parent element as popper container var element = this.dropup && this.right || this.split ? this.$el : this.$refs.toggle; // Make sure we have a reference to an element, not a component! element = element.$el || element; // Instantiate popper.js this.createPopper(element); } } this.setTouchStart(true); this.$emit('shown'); // Focus on the first item on show this.$nextTick(this.focusFirstItem); }, hideMenu: function hideMenu() { this.setTouchStart(false); this.emitOnRoot('bv::dropdown::hidden', this); this.$emit('hidden'); this.removePopper(); }, createPopper: function createPopper(element) { this.removePopper(); this._popper = new Popper(element, this.$refs.menu, this.getPopperConfig()); }, removePopper: function removePopper() { if (this._popper) { // Ensure popper event listeners are removed cleanly this._popper.destroy(); } this._popper = null; }, getPopperConfig /* istanbul ignore next: can't test popper in JSDOM */: function getPopperConfig() { var placement = AttachmentMap.BOTTOM; if (this.dropup && this.right) { // dropup + right placement = AttachmentMap.TOPEND; } else if (this.dropup) { // dropup + left placement = AttachmentMap.TOP; } else if (this.right) { // dropdown + right placement = AttachmentMap.BOTTOMEND; } var popperConfig = { placement: placement, modifiers: { offset: { offset: this.offset || 0 }, flip: { enabled: !this.noFlip } } }; if (this.boundary) { popperConfig.modifiers.preventOverflow = { boundariesElement: this.boundary }; } return assign(popperConfig, this.popperOpts || {}); }, setTouchStart: function setTouchStart(on) { var _this = this; /* * If this is a touch-enabled device we add extra * empty mouseover listeners to the body's immediate children; * only needed because of broken event delegation on iOS * https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html */ if ('ontouchstart' in document.documentElement) { var children = from(document.body.children); children.forEach(function (el) { if (on) { eventOn('mouseover', _this._noop); } else { eventOff('mouseover', _this._noop); } }); } }, /* istanbul ignore next: not easy to test */ _noop: function _noop() { // Do nothing event handler (used in touchstart event handler) }, rootCloseListener: function rootCloseListener(vm) { if (vm !== this) { this.visible = false; } }, clickOutListener: function clickOutListener() { this.visible = false; }, show: function show() { // Public method to show dropdown if (this.disabled) { return; } this.visible = true; }, hide: function hide() { // Public method to hide dropdown if (this.disabled) { return; } this.visible = false; }, toggle: function toggle(evt) { // Called only by a button that toggles the menu evt = evt || {}; var type = evt.type; var key = evt.keyCode; if (type !== 'click' && !(type === 'keydown' && (key === KeyCodes.ENTER || key === KeyCodes.SPACE || key === KeyCodes.DOWN))) { // We only toggle on Click, Enter, Space, and Arrow Down return; } if (this.disabled) { this.visible = false; return; } this.$emit('toggle', evt); if (evt.defaultPrevented) { // Exit if canceled return; } evt.preventDefault(); evt.stopPropagation(); // Toggle visibility this.visible = !this.visible; }, click: function click(evt) { // Calle only in split button mode, for the split button if (this.disabled) { this.visible = false; return; } this.$emit('click', evt); }, /* istanbul ignore next: not easy to test */ onKeydown: function onKeydown(evt) { // Called from dropdown menu context var key = evt.keyCode; if (key === KeyCodes.ESC) { // Close on ESC this.onEsc(evt); } else if (key === KeyCodes.TAB) { // Close on tab out this.onTab(evt); } else if (key === KeyCodes.DOWN) { // Down Arrow this.focusNext(evt, false); } else if (key === KeyCodes.UP) { // Up Arrow this.focusNext(evt, true); } }, /* istanbul ignore next: not easy to test */ onEsc: function onEsc(evt) { if (this.visible) { this.visible = false; evt.preventDefault(); evt.stopPropagation(); // Return focus to original trigger button this.$nextTick(this.focusToggler); } }, /* istanbul ignore next: not easy to test */ onTab: function onTab(evt) { if (this.visible) { // TODO: Need special handler for dealing with form inputs // Tab, if in a text-like input, we should just focus next item in the dropdown // Note: Inputs are in a special .dropdown-form container this.visible = false; } }, onFocusOut: function onFocusOut(evt) { if (this.$refs.menu.contains(evt.relatedTarget)) { return; } this.visible = false; }, /* istanbul ignore next: not easy to test */ onMouseOver: function onMouseOver(evt) { // Focus the item on hover // TODO: Special handling for inputs? Inputs are in a special .dropdown-form container var item = evt.target; if (item.classList.contains('dropdown-item') && !item.disabled && !item.classList.contains('disabled') && item.focus) { item.focus(); } }, focusNext: function focusNext(evt, up) { var _this2 = this; if (!this.visible) { return; } evt.preventDefault(); evt.stopPropagation(); this.$nextTick(function () { var items = _this2.getItems(); if (items.length < 1) { return; } var index = items.indexOf(evt.target); if (up && index > 0) { index--; } else if (!up && index < items.length - 1) { index++; } if (index < 0) { index = 0; } _this2.focusItem(index, items); }); }, focusItem: function focusItem(idx, items) { var el = items.find(function (el, i) { return i === idx; }); if (el && getAttr(el, 'tabindex') !== '-1') { el.focus(); } }, getItems: function getItems() { // Get all items return filterVisible(selectAll(ITEM_SELECTOR$1, this.$refs.menu)); }, getFirstItem: function getFirstItem() { // Get the first non-disabled item var item = this.getItems()[0]; return item || null; }, focusFirstItem: function focusFirstItem() { var item = this.getFirstItem(); if (item) { this.focusItem(0, [item]); } }, focusToggler: function focusToggler() { var toggler = this.toggler; if (toggler && toggler.focus) { toggler.focus(); } } } }; var bDropdown = { mixins: [idMixin, dropdownMixin], components: { bButton: bBtn }, render: function render(h) { var split = h(false); if (this.split) { split = h('b-button', { ref: 'button', props: { disabled: this.disabled, variant: this.variant, size: this.size }, attrs: { id: this.safeId('_BV_button_') }, on: { click: this.click } }, [this.$slots['button-content'] || this.$slots.text || this.text]); } var toggle = h('b-button', { ref: 'toggle', class: this.toggleClasses, props: { variant: this.variant, size: this.size, disabled: this.disabled }, attrs: { id: this.safeId('_BV_toggle_'), 'aria-haspopup': 'true', 'aria-expanded': this.visible ? 'true' : 'false' }, on: { click: this.toggle, // click keydown: this.toggle // enter, space, down } }, [this.split ? h('span', { class: ['sr-only'] }, [this.toggleText]) : this.$slots['button-content'] || this.$slots.text || this.text]); var menu = h('div', { ref: 'menu', class: this.menuClasses, attrs: { role: this.role, 'aria-labelledby': this.safeId(this.split ? '_BV_button_' : '_BV_toggle_') }, on: { mouseover: this.onMouseOver, keydown: this.onKeydown // tab, up, down, esc } }, [this.$slots.default]); return h('div', { attrs: { id: this.safeId() }, class: this.dropdownClasses }, [split, toggle, menu]); }, props: { split: { type: Boolean, default: false }, toggleText: { type: String, default: 'Toggle Dropdown' }, size: { type: String, default: null }, variant: { type: String, default: null }, menuClass: { type: [String, Array], default: null }, toggleClass: { type: [String, Array], default: null }, noCaret: { type: Boolean, default: false }, role: { type: String, default: 'menu' }, boundary: { // String: `scrollParent`, `window` or `viewport` // Object: HTML Element reference type: [String, Object], default: 'scrollParent' } }, computed: { dropdownClasses: function dropdownClasses() { var position = ''; // Position `static` is needed to allow menu to "breakout" of the scrollParent boundaries // when boundary is anything other than `scrollParent` // See https://github.com/twbs/bootstrap/issues/24251#issuecomment-341413786 if (this.boundary !== 'scrollParent' || !this.boundary) { position = 'position-static'; } return ['btn-group', 'b-dropdown', 'dropdown', this.dropup ? 'dropup' : '', this.visible ? 'show' : '', position]; }, menuClasses: function menuClasses() { return ['dropdown-menu', { 'dropdown-menu-right': this.right, 'show': this.visible }, this.menuClass]; }, toggleClasses: function toggleClasses() { return [{ 'dropdown-toggle': !this.noCaret || this.split, 'dropdown-toggle-split': this.split }, this.toggleClass]; } } }; var props$l = propsFactory(); var bDropdownItem = { functional: true, props: props$l, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(bLink, mergeData(data, { props: props, staticClass: 'dropdown-item', attrs: { role: 'menuitem' } }), children); } }; var props$m = { disabled: { type: Boolean, default: false } }; var bDropdownItemButton = { functional: true, props: props$m, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, parent = _ref.parent, children = _ref.children; return h('button', mergeData(data, { props: props, staticClass: 'dropdown-item', attrs: { role: 'menuitem', type: 'button', disabled: props.disabled }, on: { click: function click(e) { parent.$root.$emit('clicked::link', e); } } }), children); } }; var props$n = { id: { type: String, default: null }, tag: { type: String, default: 'h6' } }; var bDropdownHeader = { functional: true, props: props$n, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'dropdown-header', attrs: { id: props.id || null } }), children); } }; var props$o = { tag: { type: String, default: 'div' } }; var bDropdownDivider = { functional: true, props: props$o, render: function render(h, _ref) { var props = _ref.props, data = _ref.data; return h(props.tag, mergeData(data, { staticClass: 'dropdown-divider', attrs: { role: 'separator' } })); } }; var components$b = { bDropdown: bDropdown, bDd: bDropdown, bDropdownItem: bDropdownItem, bDdItem: bDropdownItem, bDropdownItemButton: bDropdownItemButton, bDropdownItemBtn: bDropdownItemButton, bDdItemButton: bDropdownItemButton, bDdItemBtn: bDropdownItemButton, bDropdownHeader: bDropdownHeader, bDdHeader: bDropdownHeader, bDropdownDivider: bDropdownDivider, bDdDivider: bDropdownDivider }; var VuePlugin$c = { install: function install(Vue) { registerComponents(Vue, components$b); } }; vueUse(VuePlugin$c); var props$p = { type: { type: String, default: 'iframe', validator: function validator(str) { return arrayIncludes(['iframe', 'embed', 'video', 'object', 'img', 'b-img', 'b-img-lazy'], str); } }, tag: { type: String, default: 'div' }, aspect: { type: String, default: '16by9' } }; var bEmbed = { functional: true, props: props$p, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, { ref: data.ref, staticClass: 'embed-responsive', class: defineProperty({}, 'embed-responsive-' + props.aspect, Boolean(props.aspect)) }, [h(props.type, mergeData(data, { ref: '', staticClass: 'embed-responsive-item' }), children)]); } }; var components$c = { bEmbed: bEmbed }; var VuePlugin$d = { install: function install(Vue) { registerComponents(Vue, components$c); } }; vueUse(VuePlugin$d); var props$q = { id: { type: String, default: null }, inline: { type: Boolean, default: false }, novalidate: { type: Boolean, default: false }, validated: { type: Boolean, default: false } }; var Form = { functional: true, props: props$q, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h('form', mergeData(data, { class: { 'form-inline': props.inline, 'was-validated': props.validated }, attrs: { id: props.id, novalidate: props.novalidate } }), children); } }; var props$r = { id: { type: String, default: null }, tag: { type: String, default: 'small' }, textVariant: { type: String, default: 'muted' }, inline: { type: Boolean, default: false } }; var bFormText = { functional: true, props: props$r, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { class: defineProperty({ 'form-text': !props.inline }, 'text-' + props.textVariant, Boolean(props.textVariant)), attrs: { id: props.id } }), children); } }; var props$s = { id: { type: String, default: null }, tag: { type: String, default: 'div' }, forceShow: { type: Boolean, default: false } }; var bFormInvalidFeedback = { functional: true, props: props$s, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'invalid-feedback', class: { 'd-block': props.forceShow }, attrs: { id: props.id } }), children); } }; var props$t = { id: { type: String, default: null }, tag: { type: String, default: 'div' }, forceShow: { type: Boolean, default: false } }; var bFormValidFeedback = { functional: true, props: props$t, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'valid-feedback', class: { 'd-block': props.forceShow }, attrs: { id: props.id } }), children); } }; var components$d = { bForm: Form, bFormRow: bFormRow, bFormText: bFormText, bFormInvalidFeedback: bFormInvalidFeedback, bFormFeedback: bFormInvalidFeedback, bFormValidFeedback: bFormValidFeedback }; var VuePlugin$e = { install: function install(Vue) { registerComponents(Vue, components$d); } }; vueUse(VuePlugin$e); /* Form control contextual state class computation * * Returned class is either 'is-valid' or 'is-invalid' based on the 'state' prop * state can be one of five values: * - true or 'valid' for is-valid * - false or 'invalid' for is-invalid * - null (or empty string) for no contextual state */ var formStateMixin = { props: { state: { // true/'valid', false/'invalid', '',null type: [Boolean, String], default: null } }, computed: { computedState: function computedState() { var state = this.state; if (state === true || state === 'valid') { return true; } else if (state === false || state === 'invalid') { return false; } return null; }, stateClass: function stateClass() { var state = this.computedState; if (state === true) { return 'is-valid'; } else if (state === false) { return 'is-invalid'; } return null; } } }; // Selector for finding firt input in the form-group var SELECTOR = 'input:not(:disabled),textarea:not(:disabled),select:not(:disabled)'; var bFormGroup = { mixins: [idMixin, formStateMixin], components: { bFormRow: bFormRow, bFormText: bFormText, bFormInvalidFeedback: bFormInvalidFeedback, bFormValidFeedback: bFormValidFeedback }, render: function render(h) { var $slots = this.$slots; // Label / Legend var legend = h(false); if (this.hasLabel) { var children = $slots['label']; var legendTag = this.labelFor ? 'label' : 'legend'; var legendDomProps = children ? {} : { innerHTML: this.label }; var legendAttrs = { id: this.labelId, for: this.labelFor || null }; var legendClick = this.labelFor || this.labelSrOnly ? {} : { click: this.legendClick }; if (this.horizontal) { // Horizontal layout with label if (this.labelSrOnly) { // SR Only we wrap label/legend in a div to preserve layout children = h(legendTag, { class: ['sr-only'], attrs: legendAttrs, domProps: legendDomProps }, children); legend = h('div', { class: this.labelLayoutClasses }, [children]); } else { legend = h(legendTag, { class: [this.labelLayoutClasses, this.labelClasses], attrs: legendAttrs, domProps: legendDomProps, on: legendClick }, children); } } else { // Vertical layout with label legend = h(legendTag, { class: this.labelSrOnly ? ['sr-only'] : this.labelClasses, attrs: legendAttrs, domProps: legendDomProps, on: legendClick }, children); } } else if (this.horizontal) { // No label but has horizontal layout, so we need a spacer element for layout legend = h('div', { class: this.labelLayoutClasses }); } // Invalid feeback text (explicitly hidden if state is valid) var invalidFeedback = h(false); if (this.hasInvalidFeedback) { var domProps = {}; if (!$slots['invalid-feedback'] && !$slots['feedback']) { domProps = { innerHTML: this.invalidFeedback || this.feedback || '' }; } invalidFeedback = h('b-form-invalid-feedback', { props: { id: this.invalidFeedbackId, forceShow: this.computedState === false }, attrs: { role: 'alert', 'aria-live': 'assertive', 'aria-atomic': 'true' }, domProps: domProps }, $slots['invalid-feedback'] || $slots['feedback']); } // Valid feeback text (explicitly hidden if state is invalid) var validFeedback = h(false); if (this.hasValidFeedback) { var _domProps = $slots['valid-feedback'] ? {} : { innerHTML: this.validFeedback || '' }; validFeedback = h('b-form-valid-feedback', { props: { id: this.validFeedbackId, forceShow: this.computedState === true }, attrs: { role: 'alert', 'aria-live': 'assertive', 'aria-atomic': 'true' }, domProps: _domProps }, $slots['valid-feedback']); } // Form help text (description) var description = h(false); if (this.hasDescription) { var _domProps2 = $slots['description'] ? {} : { innerHTML: this.description || '' }; description = h('b-form-text', { attrs: { id: this.descriptionId }, domProps: _domProps2 }, $slots['description']); } // Build content layout var content = h('div', { ref: 'content', class: this.inputLayoutClasses, attrs: this.labelFor ? {} : { role: 'group', 'aria-labelledby': this.labelId } }, [$slots['default'], invalidFeedback, validFeedback, description]); // Generate main form-group wrapper return h(this.labelFor ? 'div' : 'fieldset', { class: this.groupClasses, attrs: { id: this.safeId(), disabled: this.disabled, role: 'group', 'aria-invalid': this.computedState === false ? 'true' : null, 'aria-labelledby': this.labelId, 'aria-describedby': this.labelFor ? null : this.describedByIds } }, this.horizontal ? [h('b-form-row', {}, [legend, content])] : [legend, content]); }, props: { horizontal: { type: Boolean, default: false }, labelCols: { type: [Number, String], default: 3, validator: function validator(value) { if (Number(value) >= 1 && Number(value) <= 11) { return true; } warn('b-form-group: label-cols must be a value between 1 and 11'); return false; } }, breakpoint: { type: String, default: 'sm' }, labelTextAlign: { type: String, default: null }, label: { type: String, default: null }, labelFor: { type: String, default: null }, labelSize: { type: String, default: null }, labelSrOnly: { type: Boolean, default: false }, labelClass: { type: [String, Array], default: null }, description: { type: String, default: null }, invalidFeedback: { type: String, default: null }, feedback: { // Deprecated in favor of invalid-feedback type: String, default: null }, validFeedback: { type: String, default: null }, validated: { type: Boolean, default: false } }, computed: { groupClasses: function groupClasses() { return ['b-form-group', 'form-group', this.validated ? 'was-validated' : null, this.stateClass]; }, labelClasses: function labelClasses() { return ['col-form-label', this.labelSize ? 'col-form-label-' + this.labelSize : null, this.labelTextAlign ? 'text-' + this.labelTextAlign : null, this.horizontal ? null : 'pt-0', this.labelClass]; }, labelLayoutClasses: function labelLayoutClasses() { return [this.horizontal ? 'col-' + this.breakpoint + '-' + this.labelCols : null]; }, inputLayoutClasses: function inputLayoutClasses() { return [this.horizontal ? 'col-' + this.breakpoint + '-' + (12 - Number(this.labelCols)) : null]; }, hasLabel: function hasLabel() { return this.label || this.$slots['label']; }, hasDescription: function hasDescription() { return this.description || this.$slots['description']; }, hasInvalidFeedback: function hasInvalidFeedback() { if (this.computedState === true) { // If the form-group state is explicityly valid, we return false return false; } return this.invalidFeedback || this.feedback || this.$slots['invalid-feedback'] || this.$slots['feedback']; }, hasValidFeedback: function hasValidFeedback() { if (this.computedState === false) { // If the form-group state is explicityly invalid, we return false return false; } return this.validFeedback || this.$slots['valid-feedback']; }, labelId: function labelId() { return this.hasLabel ? this.safeId('_BV_label_') : null; }, descriptionId: function descriptionId() { return this.hasDescription ? this.safeId('_BV_description_') : null; }, invalidFeedbackId: function invalidFeedbackId() { return this.hasInvalidFeedback ? this.safeId('_BV_feedback_invalid_') : null; }, validFeedbackId: function validFeedbackId() { return this.hasValidFeedback ? this.safeId('_BV_feedback_valid_') : null; }, describedByIds: function describedByIds() { return [this.descriptionId, this.invalidFeedbackId, this.validFeedbackId].filter(function (i) { return i; }).join(' ') || null; } }, watch: { describedByIds: function describedByIds(add, remove) { if (add !== remove) { this.setInputDescribedBy(add, remove); } } }, methods: { legendClick: function legendClick(evt) { var tagName = evt.target ? evt.target.tagName : ''; if (/^(input|select|textarea|label)$/i.test(tagName)) { // If clicked an input inside legend, we just let the default happen return; } // Focus the first non-disabled visible input when the legend element is clicked var inputs = selectAll(SELECTOR, this.$refs.content).filter(isVisible); if (inputs[0] && inputs[0].focus) { inputs[0].focus(); } }, setInputDescribedBy: function setInputDescribedBy(add, remove) { // Sets the `aria-describedby` attribute on the input if label-for is set. // Optionally accepts a string of IDs to remove as the second parameter if (this.labelFor && typeof document !== 'undefined') { var input = select('#' + this.labelFor, this.$refs.content); if (input) { var adb = 'aria-describedby'; var ids = (getAttr(input, adb) || '').split(/\s+/); remove = (remove || '').split(/\s+/); // Update ID list, preserving any original IDs ids = ids.filter(function (id) { return remove.indexOf(id) === -1; }).concat(add || '').join(' ').trim(); if (ids) { setAttr(input, adb, ids); } else { removeAttr(input, adb); } } } } }, mounted: function mounted() { var _this = this; this.$nextTick(function () { // Set the adia-describedby IDs on the input specified by label-for // We do this in a nextTick to ensure the children have finished rendering _this.setInputDescribedBy(_this.describedByIds); }); } }; var components$e = { bFormGroup: bFormGroup, bFormFieldset: bFormGroup }; var VuePlugin$f = { install: function install(Vue) { registerComponents(Vue, components$e); } }; vueUse(VuePlugin$f); /* * form-radio & form-check mixin * */ var formRadioCheckMixin = { data: function data() { return { localChecked: this.checked, hasFocus: false }; }, model: { prop: 'checked', event: 'input' }, props: { value: {}, checked: { // This is the model, except when in group mode }, buttonVariant: { // Only applicable when rendered with button style type: String, default: null } }, computed: { computedLocalChecked: { get: function get() { if (this.is_Child) { return this.$parent.localChecked; } else { return this.localChecked; } }, set: function set(val) { if (this.is_Child) { this.$parent.localChecked = val; } else { this.localChecked = val; } } }, is_Child: function is_Child() { return Boolean(this.$parent && this.$parent.is_RadioCheckGroup); }, is_Disabled: function is_Disabled() { // Child can be disabled while parent isn't return Boolean(this.is_Child ? this.$parent.disabled || this.disabled : this.disabled); }, is_Required: function is_Required() { return Boolean(this.is_Child ? this.$parent.required : this.required); }, is_Plain: function is_Plain() { return Boolean(this.is_Child ? this.$parent.plain : this.plain); }, is_Custom: function is_Custom() { return !this.is_Plain; }, get_Size: function get_Size() { return this.is_Child ? this.$parent.size : this.size; }, get_State: function get_State() { // This is a tri-state prop (true, false, null) if (this.is_Child && typeof this.$parent.get_State === 'boolean') { return this.$parent.get_State; } return this.computedState; }, get_StateClass: function get_StateClass() { // This is a tri-state prop (true, false, null) return typeof this.get_State === 'boolean' ? this.get_State ? 'is-valid' : 'is-invalid' : ''; }, is_Stacked: function is_Stacked() { return Boolean(this.is_Child && this.$parent.stacked); }, is_Inline: function is_Inline() { return !this.is_Stacked; }, is_ButtonMode: function is_ButtonMode() { return Boolean(this.is_Child && this.$parent.buttons); }, get_ButtonVariant: function get_ButtonVariant() { // Local variant trumps parent variant return this.buttonVariant || (this.is_Child ? this.$parent.buttonVariant : null) || 'secondary'; }, get_Name: function get_Name() { return (this.is_Child ? this.$parent.name || this.$parent.safeId() : this.name) || null; }, buttonClasses: function buttonClasses() { // Same for radio & check return ['btn', 'btn-' + this.get_ButtonVariant, this.get_Size ? 'btn-' + this.get_Size : '', // 'disabled' class makes "button" look disabled this.is_Disabled ? 'disabled' : '', // 'active' class makes "button" look pressed this.is_Checked ? 'active' : '', // Focus class makes button look focused this.hasFocus ? 'focus' : '']; } }, methods: { handleFocus: function handleFocus(evt) { // When in buttons mode, we need to add 'focus' class to label when radio focused if (this.is_ButtonMode && evt.target) { if (evt.type === 'focus') { this.hasFocus = true; } else if (evt.type === 'blur') { this.hasFocus = false; } } } } }; var formMixin = { props: { name: { type: String }, id: { type: String }, disabled: { type: Boolean }, required: { type: Boolean, default: false } } }; var formSizeMixin = { props: { size: { type: String, default: null } }, computed: { sizeFormClass: function sizeFormClass() { return [this.size ? "form-control-" + this.size : null]; }, sizeBtnClass: function sizeBtnClass() { return [this.size ? "btn-" + this.size : null]; } } }; var formCustomMixin = { computed: { custom: function custom() { return !this.plain; } }, props: { plain: { type: Boolean, default: false } } }; /** * Quick object check - this is primarily used to tell * Objects from primitive values when we know the value * is a JSON-compliant type. */ function isObject(obj) { return obj !== null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object'; } /** * Check if two values are loosely equal - that is, * if they are plain objects, do they have the same shape? * Returns boolean true or false */ function looseEqual(a, b) { if (a === b) return true; var isObjectA = isObject(a); var isObjectB = isObject(b); if (isObjectA && isObjectB) { try { var isArrayA = isArray(a); var isArrayB = isArray(b); if (isArrayA && isArrayB) { return a.length === b.length && a.every(function (e, i) { return looseEqual(e, b[i]); }); } else if (!isArrayA && !isArrayB) { var keysA = keys(a); var keysB = keys(b); return keysA.length === keysB.length && keysA.every(function (key) { return looseEqual(a[key], b[key]); }); } else { return false; } } catch (e) { return false; } } else if (!isObjectA && !isObjectB) { return String(a) === String(b); } else { return false; } } var bFormCheckbox = { mixins: [idMixin, formRadioCheckMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin], render: function render(h) { var _this = this; var input = h('input', { ref: 'check', class: [this.is_ButtonMode ? '' : this.is_Plain ? 'form-check-input' : 'custom-control-input', this.get_StateClass], directives: [{ name: 'model', rawName: 'v-model', value: this.computedLocalChecked, expression: 'computedLocalChecked' }], attrs: { id: this.safeId(), type: 'checkbox', name: this.get_Name, disabled: this.is_Disabled, required: this.is_Required, autocomplete: 'off', 'true-value': this.value, 'false-value': this.uncheckedValue, 'aria-required': this.is_Required ? 'true' : null }, domProps: { value: this.value, checked: this.is_Checked }, on: { focus: this.handleFocus, blur: this.handleFocus, change: this.emitChange, __c: function __c(evt) { var $$a = _this.computedLocalChecked; var $$el = evt.target; if (isArray($$a)) { // Multiple checkbox var $$v = _this.value; var $$i = _this._i($$a, $$v); // Vue's 'loose' Array.indexOf if ($$el.checked) { // Append value to array $$i < 0 && (_this.computedLocalChecked = $$a.concat([$$v])); } else { // Remove value from array $$i > -1 && (_this.computedLocalChecked = $$a.slice(0, $$i).concat($$a.slice($$i + 1))); } } else { // Single checkbox _this.computedLocalChecked = $$el.checked ? _this.value : _this.uncheckedValue; } } } }); var description = h(this.is_ButtonMode ? 'span' : 'label', { class: this.is_ButtonMode ? null : this.is_Plain ? 'form-check-label' : 'custom-control-label', attrs: { for: this.is_ButtonMode ? null : this.safeId() } }, [this.$slots.default]); if (!this.is_ButtonMode) { return h('div', { class: [this.is_Plain ? 'form-check' : this.labelClasses, { 'form-check-inline': this.is_Plain && !this.is_Stacked }, { 'custom-control-inline': !this.is_Plain && !this.is_Stacked }] }, [input, description]); } else { return h('label', { class: [this.buttonClasses] }, [input, description]); } }, props: { value: { default: true }, uncheckedValue: { // Not applicable in multi-check mode default: false }, indeterminate: { // Not applicable in multi-check mode type: Boolean, default: false } }, computed: { labelClasses: function labelClasses() { return ['custom-control', 'custom-checkbox', this.get_Size ? 'form-control-' + this.get_Size : '', this.get_StateClass]; }, is_Checked: function is_Checked() { var checked = this.computedLocalChecked; if (isArray(checked)) { for (var i = 0; i < checked.length; i++) { if (looseEqual(checked[i], this.value)) { return true; } } return false; } else { return looseEqual(checked, this.value); } } }, watch: { computedLocalChecked: function computedLocalChecked(newVal, oldVal) { if (looseEqual(newVal, oldVal)) { return; } this.$emit('input', newVal); this.$emit('update:indeterminate', this.$refs.check.indeterminate); }, checked: function checked(newVal, oldVal) { if (this.is_Child || looseEqual(newVal, oldVal)) { return; } this.computedLocalChecked = newVal; }, indeterminate: function indeterminate(newVal, oldVal) { this.setIndeterminate(newVal); } }, methods: { emitChange: function emitChange(_ref) { var checked = _ref.target.checked; // Change event is only fired via user interaction // And we only emit the value of this checkbox if (this.is_Child || isArray(this.computedLocalChecked)) { this.$emit('change', checked ? this.value : null); if (this.is_Child) { // If we are a child of form-checkbbox-group, emit change on parent this.$parent.$emit('change', this.computedLocalChecked); } } else { // Single radio mode supports unchecked value this.$emit('change', checked ? this.value : this.uncheckedValue); } this.$emit('update:indeterminate', this.$refs.check.indeterminate); }, setIndeterminate: function setIndeterminate(state) { // Indeterminate only supported in single checkbox mode if (this.is_Child || isArray(this.computedLocalChecked)) { return; } this.$refs.check.indeterminate = state; // Emit update event to prop this.$emit('update:indeterminate', this.$refs.check.indeterminate); } }, mounted: function mounted() { // Set initial indeterminate state this.setIndeterminate(this.indeterminate); } }; function isObject$1(obj) { return obj && {}.toString.call(obj) === '[object Object]'; } var formOptionsMixin = { props: { options: { type: [Array, Object], default: function _default() { return []; } }, valueField: { type: String, default: 'value' }, textField: { type: String, default: 'text' }, disabledField: { type: String, default: 'disabled' } }, computed: { formOptions: function formOptions() { var options = this.options; var valueField = this.valueField; var textField = this.textField; var disabledField = this.disabledField; if (isArray(options)) { // Normalize flat-ish arrays to Array of Objects return options.map(function (option) { if (isObject$1(option)) { return { value: option[valueField], text: String(option[textField]), disabled: option[disabledField] || false }; } return { value: option, text: String(option), disabled: false }; }); } else { // options is Object // Normalize Objects to Array of Objects return keys(options).map(function (key) { var option = options[key] || {}; if (isObject$1(option)) { var value = option[valueField]; var text = option[textField]; return { value: typeof value === 'undefined' ? key : value, text: typeof text === 'undefined' ? key : String(text), disabled: option[disabledField] || false }; } return { value: key, text: String(option), disabled: false }; }); } } } }; var bFormCheckboxGroup = { mixins: [idMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin, formOptionsMixin], components: { bFormCheckbox: bFormCheckbox }, render: function render(h) { var _this = this; var $slots = this.$slots; var checks = this.formOptions.map(function (option, idx) { return h('b-form-checkbox', { key: 'check_' + idx + '_opt', props: { id: _this.safeId('_BV_check_' + idx + '_opt_'), name: _this.name, value: option.value, required: _this.name && _this.required, disabled: option.disabled } }, [h('span', { domProps: { innerHTML: option.text } })]); }); return h('div', { class: this.groupClasses, attrs: { id: this.safeId(), role: 'group', tabindex: '-1', 'aria-required': this.required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid } }, [$slots.first, checks, $slots.default]); }, data: function data() { return { localChecked: this.checked || [], // Flag for children is_RadioCheckGroup: true }; }, model: { prop: 'checked', event: 'input' }, props: { checked: { type: [String, Number, Object, Array, Boolean], default: null }, validated: { type: Boolean, default: false }, ariaInvalid: { type: [Boolean, String], default: false }, stacked: { type: Boolean, default: false }, buttons: { // Render as button style type: Boolean, default: false }, buttonVariant: { // Only applicable when rendered with button style type: String, default: 'secondary' } }, watch: { checked: function checked(newVal, oldVal) { this.localChecked = this.checked; }, localChecked: function localChecked(newVal, oldVal) { this.$emit('input', newVal); } }, computed: { groupClasses: function groupClasses() { if (this.buttons) { return ['btn-group-toggle', this.stacked ? 'btn-group-vertical' : 'btn-group', this.size ? 'btn-group-' + this.size : '', this.validated ? 'was-validated' : '']; } return [this.sizeFormClass, this.stacked && this.custom ? 'custom-controls-stacked' : '', this.validated ? 'was-validated' : '']; }, computedAriaInvalid: function computedAriaInvalid() { if (this.ariaInvalid === true || this.ariaInvalid === 'true' || this.ariaInvalid === '') { return 'true'; } return this.get_State === false ? 'true' : null; }, get_State: function get_State() { // Child radios sniff this value return this.computedState; } } }; var components$f = { bFormCheckbox: bFormCheckbox, bCheckbox: bFormCheckbox, bCheck: bFormCheckbox, bFormCheckboxGroup: bFormCheckboxGroup, bCheckboxGroup: bFormCheckboxGroup, bCheckGroup: bFormCheckboxGroup }; var VuePlugin$g = { install: function install(Vue) { registerComponents(Vue, components$f); } }; vueUse(VuePlugin$g); var bFormRadio = { mixins: [idMixin, formRadioCheckMixin, formMixin, formStateMixin], render: function render(h) { var _this = this; var input = h('input', { ref: 'radio', class: [this.is_ButtonMode ? '' : this.is_Plain ? 'form-check-input' : 'custom-control-input', this.get_StateClass], directives: [{ name: 'model', rawName: 'v-model', value: this.computedLocalChecked, expression: 'computedLocalChecked' }], attrs: { id: this.safeId(), type: 'radio', name: this.get_Name, required: this.get_Name && this.is_Required, disabled: this.is_Disabled, autocomplete: 'off' }, domProps: { value: this.value, checked: looseEqual(this.computedLocalChecked, this.value) }, on: { focus: this.handleFocus, blur: this.handleFocus, change: this.emitChange, __c: function __c(evt) { _this.computedLocalChecked = _this.value; } } }); var description = h(this.is_ButtonMode ? 'span' : 'label', { class: this.is_ButtonMode ? null : this.is_Plain ? 'form-check-label' : 'custom-control-label', attrs: { for: this.is_ButtonMode ? null : this.safeId() } }, [this.$slots.default]); if (!this.is_ButtonMode) { return h('div', { class: [this.is_Plain ? 'form-check' : this.labelClasses, { 'form-check-inline': this.is_Plain && !this.is_Stacked }, { 'custom-control-inline': !this.is_Plain && !this.is_Stacked }] }, [input, description]); } else { return h('label', { class: [this.buttonClasses] }, [input, description]); } }, watch: { // Radio Groups can only have a single value, so our watchers are simple checked: function checked(newVal, oldVal) { this.computedLocalChecked = newVal; }, computedLocalChceked: function computedLocalChceked(newVal, oldVal) { this.$emit('input', this.computedLocalChceked); } }, computed: { is_Checked: function is_Checked() { return looseEqual(this.value, this.computedLocalChecked); }, labelClasses: function labelClasses() { // Specific to radio return [this.get_Size ? 'form-control-' + this.get_Size : '', 'custom-control', 'custom-radio', this.get_StateClass]; } }, methods: { emitChange: function emitChange(_ref) { var checked = _ref.target.checked; // Change is only emitted on user interaction this.$emit('change', checked ? this.value : null); // If this is a child of form-radio-group, we emit a change event on it as well if (this.is_Child) { this.$parent.$emit('change', this.computedLocalChecked); } } } }; var bFormRadioGroup = { mixins: [idMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin, formOptionsMixin], components: { bFormRadio: bFormRadio }, render: function render(h) { var _this = this; var $slots = this.$slots; var radios = this.formOptions.map(function (option, idx) { return h('b-form-radio', { key: 'radio_' + idx + '_opt', props: { id: _this.safeId('_BV_radio_' + idx + '_opt_'), name: _this.name, value: option.value, required: Boolean(_this.name && _this.required), disabled: option.disabled } }, [h('span', { domProps: { innerHTML: option.text } })]); }); return h('div', { class: this.groupClasses, attrs: { id: this.safeId(), role: 'radiogroup', tabindex: '-1', 'aria-required': this.required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid } }, [$slots.first, radios, $slots.default]); }, data: function data() { return { localChecked: this.checked, // Flag for children is_RadioCheckGroup: true }; }, model: { prop: 'checked', event: 'input' }, props: { checked: { type: [String, Object, Number, Boolean], default: null }, validated: { // Used for applying hte `was-validated` class to the group type: Boolean, default: false }, ariaInvalid: { type: [Boolean, String], default: false }, stacked: { type: Boolean, default: false }, buttons: { // Render as button style type: Boolean, default: false }, buttonVariant: { // Only applicable when rendered with button style type: String, default: 'secondary' } }, watch: { checked: function checked(newVal, oldVal) { this.localChecked = this.checked; }, localChecked: function localChecked(newVal, oldVal) { this.$emit('input', newVal); } }, computed: { groupClasses: function groupClasses() { if (this.buttons) { return ['btn-group-toggle', this.stacked ? 'btn-group-vertical' : 'btn-group', this.size ? 'btn-group-' + this.size : '', this.validated ? 'was-validated' : '']; } return [this.sizeFormClass, this.stacked && this.custom ? 'custom-controls-stacked' : '', this.validated ? 'was-validated' : '']; }, computedAriaInvalid: function computedAriaInvalid() { if (this.ariaInvalid === true || this.ariaInvalid === 'true' || this.ariaInvalid === '') { return 'true'; } return this.get_State === false ? 'true' : null; }, get_State: function get_State() { // Required by child radios return this.computedState; } } }; var components$g = { bFormRadio: bFormRadio, bRadio: bFormRadio, bFormRadioGroup: bFormRadioGroup, bRadioGroup: bFormRadioGroup }; var VuePlugin$h = { install: function install(Vue) { registerComponents(Vue, components$g); } }; vueUse(VuePlugin$h); // Valid supported input types var TYPES = ['text', 'password', 'email', 'number', 'url', 'tel', 'search', 'range', 'color', 'date', 'time', 'datetime', 'datetime-local', 'month', 'week']; var bFormInput = { mixins: [idMixin, formMixin, formSizeMixin, formStateMixin], render: function render(h) { return h('input', { ref: 'input', class: this.inputClass, attrs: { id: this.safeId(), name: this.name, type: this.localType, disabled: this.disabled, required: this.required, readonly: this.readonly || this.plaintext, placeholder: this.placeholder, autocomplete: this.autocomplete || null, 'aria-required': this.required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid, value: this.value }, on: { input: this.onInput, change: this.onChange } }); }, props: { value: { default: null }, type: { type: String, default: 'text', validator: function validator(type) { return arrayIncludes(TYPES, type); } }, ariaInvalid: { type: [Boolean, String], default: false }, readonly: { type: Boolean, default: false }, plaintext: { type: Boolean, default: false }, autocomplete: { type: String, default: null }, placeholder: { type: String, default: null }, formatter: { type: Function }, lazyFormatter: { type: Boolean, default: false } }, computed: { localType: function localType() { // We only allow certain types return arrayIncludes(TYPES, this.type) ? this.type : 'text'; }, inputClass: function inputClass() { return [this.plaintext ? 'form-control-plaintext' : 'form-control', this.sizeFormClass, this.stateClass]; }, computedAriaInvalid: function computedAriaInvalid() { if (!this.ariaInvalid || this.ariaInvalid === 'false') { // this.ariaInvalid is null or false or 'false' return this.computedState === false ? 'true' : null; } if (this.ariaInvalid === true) { // User wants explicit aria-invalid=true return 'true'; } // Most likely a string value (which could be 'true') return this.ariaInvalid; } }, mounted: function mounted() { if (this.value) { var fValue = this.format(this.value, null); this.setValue(fValue); } }, watch: { value: function value(newVal) { if (this.lazyFormatter) { this.setValue(newVal); } else { var fValue = this.format(newVal, null); this.setValue(fValue); } } }, methods: { format: function format(value, e) { if (this.formatter) { return this.formatter(value, e); } return value; }, setValue: function setValue(value) { this.$emit('input', value); // When formatter removes last typed character, value of text input should update to formatted value this.$refs.input.value = value; }, onInput: function onInput(evt) { var value = evt.target.value; if (this.lazyFormatter) { this.setValue(value); } else { var fValue = this.format(value, evt); this.setValue(fValue); } }, onChange: function onChange(evt) { var fValue = this.format(evt.target.value, evt); this.setValue(fValue); this.$emit('change', fValue); }, focus: function focus() { if (!this.disabled) { this.$el.focus(); } } } }; var components$h = { bFormInput: bFormInput, bInput: bFormInput }; var VuePlugin$i = { install: function install(Vue) { registerComponents(Vue, components$h); } }; vueUse(VuePlugin$i); var bFormTextarea = { mixins: [idMixin, formMixin, formSizeMixin, formStateMixin], render: function render(h) { var _this = this; return h('textarea', { ref: 'input', class: this.inputClass, style: this.inputStyle, directives: [{ name: 'model', rawName: 'v-model', value: this.localValue, expression: 'localValue' }], domProps: { value: this.value }, attrs: { id: this.safeId(), name: this.name, disabled: this.disabled, placeholder: this.placeholder, required: this.required, autocomplete: this.autocomplete || null, readonly: this.readonly || this.plaintext, rows: this.rowsCount, wrap: this.wrap || null, 'aria-required': this.required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid }, on: { input: function input(evt) { _this.localValue = evt.target.value; } } }); }, data: function data() { return { localValue: this.value }; }, props: { value: { type: String, default: '' }, ariaInvalid: { type: [Boolean, String], default: false }, readonly: { type: Boolean, default: false }, plaintext: { type: Boolean, default: false }, autocomplete: { type: String, default: null }, placeholder: { type: String, default: null }, rows: { type: [Number, String], default: null }, maxRows: { type: [Number, String], default: null }, wrap: { // 'soft', 'hard' or 'off'. Browser default is 'soft' type: String, default: 'soft' }, noResize: { type: Boolean, default: false } }, computed: { rowsCount: function rowsCount() { // A better option could be based on https://codepen.io/vsync/pen/frudD // As linebreaks aren't added until the input is submitted var rows = parseInt(this.rows, 10) || 1; var maxRows = parseInt(this.maxRows, 10) || 0; var lines = (this.localValue || '').toString().split('\n').length; return maxRows ? Math.min(maxRows, Math.max(rows, lines)) : Math.max(rows, lines); }, inputClass: function inputClass() { return [this.plaintext ? 'form-control-plaintext' : 'form-control', this.sizeFormClass, this.stateClass]; }, inputStyle: function inputStyle() { // We set width 100% in plaintext mode to get around a shortcoming in bootstrap CSS // setting noResize to true will disable the ability for the user to resize the textarea return { width: this.plaintext ? '100%' : null, resize: this.noResize ? 'none' : null }; }, computedAriaInvalid: function computedAriaInvalid() { if (!this.ariaInvalid || this.ariaInvalid === 'false') { // this.ariaInvalid is null or false or 'false' return this.computedState === false ? 'true' : null; } if (this.ariaInvalid === true) { // User wants explicit aria-invalid=true return 'true'; } // Most likely a string value (which could be the string 'true') return this.ariaInvalid; } }, watch: { value: function value(newVal, oldVal) { // Update our localValue if (newVal !== oldVal) { this.localValue = newVal; } }, localValue: function localValue(newVal, oldVal) { // update Parent value if (newVal !== oldVal) { this.$emit('input', newVal); } } }, methods: { focus: function focus() { // For external handler that may want a focus method if (!this.disabled) { this.$el.focus(); } } } }; var components$i = { bFormTextarea: bFormTextarea, bTextarea: bFormTextarea }; var VuePlugin$j = { install: function install(Vue) { registerComponents(Vue, components$i); } }; vueUse(VuePlugin$j); var bFormFile = { mixins: [idMixin, formMixin, formStateMixin, formCustomMixin], render: function render(h) { // Form Input var input = h('input', { ref: 'input', class: [{ 'form-control-file': this.plain, 'custom-file-input': this.custom, focus: this.custom && this.hasFocus }, this.stateClass], attrs: { type: 'file', id: this.safeId(), name: this.name, disabled: this.disabled, required: this.required, capture: this.capture || null, accept: this.accept || null, multiple: this.multiple, webkitdirectory: this.directory, 'aria-required': this.required ? 'true' : null, 'aria-describedby': this.plain ? null : this.safeId('_BV_file_control_') }, on: { change: this.onFileChange, focusin: this.focusHandler, focusout: this.focusHandler } }); if (this.plain) { return input; } // Overlay Labels var label = h('label', { class: ['custom-file-label', this.dragging ? 'dragging' : null], attrs: { id: this.safeId('_BV_file_control_') } }, this.selectLabel); // Return rendered custom file input return h('div', { class: ['custom-file', 'b-form-file', this.stateClass], attrs: { id: this.safeId('_BV_file_outer_') }, on: { dragover: this.dragover } }, [input, label]); }, data: function data() { return { selectedFile: null, dragging: false, hasFocus: false }; }, props: { accept: { type: String, default: '' }, // Instruct input to capture from camera capture: { type: Boolean, default: false }, placeholder: { type: String, default: undefined }, multiple: { type: Boolean, default: false }, directory: { type: Boolean, default: false }, noTraverse: { type: Boolean, default: false }, noDrop: { type: Boolean, default: false } }, computed: { selectLabel: function selectLabel() { // No file choosen if (!this.selectedFile || this.selectedFile.length === 0) { return this.placeholder; } // Multiple files if (this.multiple) { if (this.selectedFile.length === 1) { return this.selectedFile[0].name; } return this.selectedFile.map(function (file) { return file.name; }).join(', '); } // Single file return this.selectedFile.name; } }, watch: { selectedFile: function selectedFile(newVal, oldVal) { if (newVal === oldVal) { return; } if (!newVal && this.multiple) { this.$emit('input', []); } else { this.$emit('input', newVal); } } }, methods: { focusHandler: function focusHandler(evt) { // Boostrap v4.beta doesn't have focus styling for custom file input // Firefox has a borked '[type=file]:focus ~ sibling' selector issue, // So we add a 'focus' class to get around these "bugs" if (this.plain || evt.type === 'focusout') { this.hasFocus = false; } else { // Add focus styling for custom file input this.hasFocus = true; } }, reset: function reset() { try { // Wrapped in try in case IE < 11 craps out this.$refs.input.value = ''; } catch (e) {} // IE < 11 doesn't support setting input.value to '' or null // So we use this little extra hack to reset the value, just in case // This also appears to work on modern browsers as well. this.$refs.input.type = ''; this.$refs.input.type = 'file'; this.selectedFile = this.multiple ? [] : null; }, onFileChange: function onFileChange(evt) { var _this = this; // Always emit original event this.$emit('change', evt); // Check if special `items` prop is available on event (drop mode) // Can be disabled by setting no-traverse var items = evt.dataTransfer && evt.dataTransfer.items; if (items && !this.noTraverse) { var queue = []; for (var i = 0; i < items.length; i++) { var item = items[i].webkitGetAsEntry(); if (item) { queue.push(this.traverseFileTree(item)); } } Promise.all(queue).then(function (filesArr) { _this.setFiles(from(filesArr)); }); return; } // Normal handling this.setFiles(evt.target.files || evt.dataTransfer.files); }, setFiles: function setFiles(files) { if (!files) { this.selectedFile = null; return; } if (!this.multiple) { this.selectedFile = files[0]; return; } // Convert files to array var filesArray = []; for (var i = 0; i < files.length; i++) { if (files[i].type.match(this.accept)) { filesArray.push(files[i]); } } this.selectedFile = filesArray; }, dragover: function dragover(evt) { evt.preventDefault(); evt.stopPropagation(); if (this.noDrop || !this.custom) { return; } this.dragging = true; evt.dataTransfer.dropEffect = 'copy'; }, dragleave: function dragleave(evt) { evt.preventDefault(); evt.stopPropagation(); this.dragging = false; }, drop: function drop(evt) { evt.preventDefault(); evt.stopPropagation(); if (this.noDrop) { return; } this.dragging = false; if (evt.dataTransfer.files && evt.dataTransfer.files.length > 0) { this.onFileChange(evt); } }, traverseFileTree: function traverseFileTree(item, path) { var _this2 = this; // Based on http://stackoverflow.com/questions/3590058 return new Promise(function (resolve) { path = path || ''; if (item.isFile) { // Get file item.file(function (file) { file.$path = path; // Inject $path to file obj resolve(file); }); } else if (item.isDirectory) { // Get folder contents item.createReader().readEntries(function (entries) { var queue = []; for (var i = 0; i < entries.length; i++) { queue.push(_this2.traverseFileTree(entries[i], path + item.name + '/')); } Promise.all(queue).then(function (filesArr) { resolve(from(filesArr)); }); }); } }); } } }; var components$j = { bFormFile: bFormFile, bFile: bFormFile }; var VuePlugin$k = { install: function install(Vue) { registerComponents(Vue, components$j); } }; vueUse(VuePlugin$k); var bFormSelect = { mixins: [idMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin, formOptionsMixin], render: function render(h) { var _this = this; var $slots = this.$slots; var options = this.formOptions.map(function (option, index) { return h('option', { key: 'option_' + index + '_opt', attrs: { disabled: Boolean(option.disabled) }, domProps: { innerHTML: option.text, value: option.value } }); }); return h('select', { ref: 'input', class: this.inputClass, directives: [{ name: 'model', rawName: 'v-model', value: this.localValue, expression: 'localValue' }], attrs: { id: this.safeId(), name: this.name, multiple: this.multiple || null, size: this.computedSelectSize, disabled: this.disabled, required: this.required, 'aria-required': this.required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid }, on: { change: function change(evt) { var target = evt.target; var selectedVal = from(target.options).filter(function (o) { return o.selected; }).map(function (o) { return '_value' in o ? o._value : o.value; }); _this.localValue = target.multiple ? selectedVal : selectedVal[0]; _this.$emit('change', _this.localValue); } } }, [$slots.first, options, $slots.default]); }, data: function data() { return { localValue: this.value }; }, watch: { value: function value(newVal, oldVal) { this.localValue = newVal; }, localValue: function localValue(newVal, oldVal) { this.$emit('input', this.localValue); } }, props: { value: {}, multiple: { type: Boolean, default: false }, selectSize: { // Browsers default size to 0, which shows 4 rows in most browsers in multiple mode // Size of 1 can bork out firefox type: Number, default: 0 }, ariaInvalid: { type: [Boolean, String], default: false } }, computed: { computedSelectSize: function computedSelectSize() { // Custom selects with a size of zero causes the arrows to be hidden, // so dont render the size attribute in this case return !this.plain && this.selectSize === 0 ? null : this.selectSize; }, inputClass: function inputClass() { return ['form-control', this.stateClass, this.sizeFormClass, // Awaiting for https://github.com/twbs/bootstrap/issues/23058 this.plain ? null : 'custom-select', this.plain || !this.size ? null : 'custom-select-' + this.size]; }, computedAriaInvalid: function computedAriaInvalid() { if (this.ariaInvalid === true || this.ariaInvalid === 'true') { return 'true'; } return this.stateClass === 'is-invalid' ? 'true' : null; } } }; var components$k = { bFormSelect: bFormSelect, bSelect: bFormSelect }; var VuePlugin$l = { install: function install(Vue) { registerComponents(Vue, components$k); } }; vueUse(VuePlugin$l); var THROTTLE = 100; var bImgLazy = { components: { bImg: bImg }, render: function render(h) { return h('b-img', { props: { src: this.computedSrc, alt: this.alt, blank: this.computedBlank, blankColor: this.blankColor, width: this.computedWidth, height: this.computedHeight, fluid: this.fluid, fluidGrow: this.fluidGrow, block: this.block, thumbnail: this.thumbnail, rounded: this.rounded, left: this.left, right: this.right, center: this.center } }); }, data: function data() { return { isShown: false, scrollTimeout: null }; }, props: { src: { type: String, default: null, required: true }, alt: { type: String, default: null }, width: { type: [Number, String], default: null }, height: { type: [Number, String], default: null }, blankSrc: { // If null, a blank image is generated type: String, default: null }, blankColor: { type: String, default: 'transparent' }, blankWidth: { type: [Number, String], default: null }, blankHeight: { type: [Number, String], default: null }, fluid: { type: Boolean, default: false }, fluidGrow: { type: Boolean, default: false }, block: { type: Boolean, default: false }, thumbnail: { type: Boolean, default: false }, rounded: { type: [Boolean, String], default: false }, left: { type: Boolean, default: false }, right: { type: Boolean, default: false }, center: { type: Boolean, default: false }, offset: { type: [Number, String], default: 360 }, throttle: { type: [Number, String], default: THROTTLE } }, computed: { computedSrc: function computedSrc() { return !this.blankSrc || this.isShown ? this.src : this.blankSrc; }, computedBlank: function computedBlank() { return !(this.isShown || this.blankSrc); }, computedWidth: function computedWidth() { return this.isShown ? this.width : this.blankWidth || this.width; }, computedHeight: function computedHeight() { return this.isShown ? this.height : this.blankHeight || this.height; } }, mounted: function mounted() { this.setListeners(true); this.checkView(); }, activated: function activated() { this.setListeners(true); this.checkView(); }, deactivated: function deactivated() { this.setListeners(false); }, beforeDdestroy: function beforeDdestroy() { this.setListeners(false); }, methods: { setListeners: function setListeners(on) { clearTimeout(this.scrollTimer); this.scrollTimeout = null; var root = window; if (on) { eventOn(root, 'scroll', this.onScroll); eventOn(root, 'resize', this.onScroll); eventOn(root, 'orientationchange', this.onScroll); } else { eventOff(root, 'scroll', this.onScroll); eventOff(root, 'resize', this.onScroll); eventOff(root, 'orientationchange', this.onScroll); } }, checkView: function checkView() { // check bounding box + offset to see if we should show if (!isVisible(this.$el)) { // Element is hidden, so skip for now return; } var offset$$1 = parseInt(this.offset, 10) || 0; var docElement = document.documentElement; var view = { l: 0 - offset$$1, t: 0 - offset$$1, b: docElement.clientHeight + offset$$1, r: docElement.clientWidth + offset$$1 }; var box = getBCR(this.$el); if (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b) { // image is in view (or about to be in view) this.isShown = true; this.setListeners(false); } }, onScroll: function onScroll() { if (this.isShown) { this.setListeners(false); } else { clearTimeout(this.scrollTimeout); this.scrollTimeout = setTimeout(this.checkView, parseInt(this.throttle, 10) || THROTTLE); } } } }; var components$l = { bImg: bImg, bImgLazy: bImgLazy }; var VuePlugin$m = { install: function install(Vue) { registerComponents(Vue, components$l); } }; vueUse(VuePlugin$m); var props$u = { fluid: { type: Boolean, default: false }, containerFluid: { type: Boolean, default: false }, header: { type: String, default: null }, headerTag: { type: String, default: 'h1' }, headerLevel: { type: [Number, String], default: '3' }, lead: { type: String, default: null }, leadTag: { type: String, default: 'p' }, tag: { type: String, default: 'div' }, bgVariant: { type: String, default: null }, borderVariant: { type: String, default: null }, textVariant: { type: String, default: null } }; var bJumbotron = { functional: true, props: props$u, render: function render(h, _ref) { var _class2; var props = _ref.props, data = _ref.data, slots = _ref.slots; // The order of the conditionals matter. // We are building the component markup in order. var childNodes = []; var $slots = slots(); // Header if (props.header || $slots.header) { childNodes.push(h(props.headerTag, { class: defineProperty({}, 'display-' + props.headerLevel, Boolean(props.headerLevel)) }, $slots.header || props.header)); } // Lead if (props.lead || $slots.lead) { childNodes.push(h(props.leadTag, { staticClass: 'lead' }, $slots.lead || props.lead)); } // Default slot if ($slots.default) { childNodes.push($slots.default); } // If fluid, wrap content in a container/container-fluid if (props.fluid) { // Children become a child of a container childNodes = [h(Container, { props: { 'fluid': props.containerFluid } }, childNodes)]; } // Return the jumbotron return h(props.tag, mergeData(data, { staticClass: 'jumbotron', class: (_class2 = { 'jumbotron-fluid': props.fluid }, defineProperty(_class2, 'text-' + props.textVariant, Boolean(props.textVariant)), defineProperty(_class2, 'bg-' + props.bgVariant, Boolean(props.bgVariant)), defineProperty(_class2, 'border-' + props.borderVariant, Boolean(props.borderVariant)), defineProperty(_class2, 'border', Boolean(props.borderVariant)), _class2) }), childNodes); } }; var components$m = { bJumbotron: bJumbotron }; var VuePlugin$n = { install: function install(Vue) { registerComponents(Vue, components$m); } }; vueUse(VuePlugin$n); var components$n = { bLink: bLink }; var VuePlugin$o = { install: function install(Vue) { registerComponents(Vue, components$n); } }; vueUse(VuePlugin$o); var props$v = { tag: { type: String, default: 'div' }, flush: { type: Boolean, default: false } }; var bListGroup = { functional: true, props: props$v, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var componentData = { staticClass: 'list-group', class: { 'list-group-flush': props.flush } }; return h(props.tag, mergeData(data, componentData), children); } }; var actionTags = ['a', 'router-link', 'button', 'b-link']; var linkProps$2 = propsFactory(); delete linkProps$2.href.default; delete linkProps$2.to.default; var props$w = assign({ tag: { type: String, default: 'div' }, action: { type: Boolean, default: null }, button: { type: Boolean, default: null }, variant: { type: String, default: null } }, linkProps$2); var bListGroupItem = { functional: true, props: props$w, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, children = _ref.children; var tag = props.button ? 'button' : !props.href && !props.to ? props.tag : bLink; var isAction = Boolean(props.href || props.to || props.action || props.button || arrayIncludes(actionTags, props.tag)); var componentData = { staticClass: 'list-group-item', class: (_class = {}, defineProperty(_class, 'list-group-item-' + props.variant, Boolean(props.variant)), defineProperty(_class, 'list-group-item-action', isAction), defineProperty(_class, 'active', props.active), defineProperty(_class, 'disabled', props.disabled), _class), attrs: tag === 'button' && props.disabled ? { disabled: true } : {}, props: props.button ? {} : pluckProps(linkProps$2, props) }; return h(tag, mergeData(data, componentData), children); } }; var components$o = { bListGroup: bListGroup, bListGroupItem: bListGroupItem }; var VuePlugin$p = { install: function install(Vue) { registerComponents(Vue, components$o); } }; vueUse(VuePlugin$p); var props$x = { tag: { type: String, default: 'div' } }; var MediaBody = { functional: true, props: props$x, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'media-body' }), children); } }; var props$y = { tag: { type: String, default: 'div' }, verticalAlign: { type: String, default: 'top' } }; var MediaAside = { functional: true, props: props$y, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'd-flex', class: defineProperty({}, 'align-self-' + props.verticalAlign, props.verticalAlign) }), children); } }; var props$z = { tag: { type: String, default: 'div' }, rightAlign: { type: Boolean, default: false }, verticalAlign: { type: String, default: 'top' }, noBody: { type: Boolean, default: false } }; var bMedia = { functional: true, props: props$z, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, slots = _ref.slots, children = _ref.children; var childNodes = props.noBody ? children : []; var $slots = slots(); if (!props.noBody) { if ($slots.aside && !props.rightAlign) { childNodes.push(h(MediaAside, { staticClass: 'mr-3', props: { verticalAlign: props.verticalAlign } }, $slots.aside)); } childNodes.push(h(MediaBody, $slots.default)); if ($slots.aside && props.rightAlign) { childNodes.push(h(MediaAside, { staticClass: 'ml-3', props: { verticalAlign: props.verticalAlign } }, $slots.aside)); } } return h(props.tag, mergeData(data, { staticClass: 'media' }), childNodes); } }; var components$p = { bMedia: bMedia, bMediaAside: MediaAside, bMediaBody: MediaBody }; var VuePlugin$q = { install: function install(Vue) { registerComponents(Vue, components$p); } }; vueUse(VuePlugin$q); // Selectors for padding/margin adjustments var Selector = { FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', STICKY_CONTENT: '.sticky-top', NAVBAR_TOGGLER: '.navbar-toggler' // ObserveDom config };var OBSERVER_CONFIG = { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ['style', 'class'] }; var bModal = { mixins: [idMixin, listenOnRootMixin], components: { bBtn: bBtn, bBtnClose: bBtnClose }, render: function render(h) { var _this = this; var $slots = this.$slots; // Modal Header var header = h(false); if (!this.hideHeader) { var modalHeader = $slots['modal-header']; if (!modalHeader) { var closeButton = h(false); if (!this.hideHeaderClose) { closeButton = h('b-btn-close', { props: { disabled: this.is_transitioning, ariaLabel: this.headerCloseLabel, textVariant: this.headerTextVariant }, on: { click: function click(evt) { _this.hide('header-close'); } } }, [$slots['modal-header-close']]); } modalHeader = [h(this.titleTag, { class: ['modal-title'] }, [$slots['modal-title'] || this.title]), closeButton]; } header = h('header', { ref: 'header', class: this.headerClasses, attrs: { id: this.safeId('__BV_modal_header_') } }, [modalHeader]); } // Modal Body var body = h('div', { ref: 'body', class: this.bodyClasses, attrs: { id: this.safeId('__BV_modal_body_') } }, [$slots.default]); // Modal Footer var footer = h(false); if (!this.hideFooter) { var modalFooter = $slots['modal-footer']; if (!modalFooter) { var cancelButton = h(false); if (!this.okOnly) { cancelButton = h('b-btn', { props: { variant: this.cancelVariant, size: this.buttonSize, disabled: this.cancelDisabled || this.busy || this.is_transitioning }, on: { click: function click(evt) { _this.hide('cancel'); } } }, [$slots['modal-cancel'] || this.cancelTitle]); } var okButton = h('b-btn', { props: { variant: this.okVariant, size: this.buttonSize, disabled: this.okDisabled || this.busy || this.is_transitioning }, on: { click: function click(evt) { _this.hide('ok'); } } }, [$slots['modal-ok'] || this.okTitle]); modalFooter = [cancelButton, okButton]; } footer = h('footer', { ref: 'footer', class: this.footerClasses, attrs: { id: this.safeId('__BV_modal_footer_') } }, [modalFooter]); } // Assemble Modal Content var modalContent = h('div', { ref: 'content', class: ['modal-content'], attrs: { tabindex: '-1', role: 'document', 'aria-labelledby': this.hideHeader ? null : this.safeId('__BV_modal_header_'), 'aria-describedby': this.safeId('__BV_modal_body_') }, on: { focusout: this.onFocusout, click: function click(evt) { evt.stopPropagation(); // https://github.com/bootstrap-vue/bootstrap-vue/issues/1528 _this.$root.$emit('bv::dropdown::shown'); } } }, [header, body, footer]); // Modal Dialog wrapper var modalDialog = h('div', { class: this.dialogClasses }, [modalContent]); // Modal var modal = h('div', { ref: 'modal', class: this.modalClasses, directives: [{ name: 'show', rawName: 'v-show', value: this.is_visible, expression: 'is_visible' }], attrs: { id: this.safeId(), role: 'dialog', 'aria-hidden': this.is_visible ? null : 'true' }, on: { click: this.onClickOut, keydown: this.onEsc } }, [modalDialog]); // Wrap modal in transition modal = h('transition', { props: { enterClass: '', enterToClass: '', enterActiveClass: '', leaveClass: '', leaveActiveClass: '', leaveToClass: '' }, on: { 'before-enter': this.onBeforeEnter, enter: this.onEnter, 'after-enter': this.onAfterEnter, 'before-leave': this.onBeforeLeave, leave: this.onLeave, 'after-leave': this.onAfterLeave } }, [modal]); // Modal Backdrop var backdrop = h(false); if (!this.hideBackdrop && (this.is_visible || this.is_transitioning)) { backdrop = h('div', { class: this.backdropClasses, attrs: { id: this.safeId('__BV_modal_backdrop_') } }); } // Assemble modal and backdrop var outer = h(false); if (!this.is_hidden) { outer = h('div', { attrs: { id: this.safeId('__BV_modal_outer_') } }, [modal, backdrop]); } // Wrap in DIV to maintain thi.$el reference for hide/show method aceess return h('div', {}, [outer]); }, data: function data() { return { is_hidden: this.lazy || false, is_visible: false, is_transitioning: false, is_show: false, is_block: false, scrollbarWidth: 0, isBodyOverflowing: false, return_focus: this.returnFocus || null }; }, model: { prop: 'visible', event: 'change' }, props: { title: { type: String, default: '' }, titleTag: { type: String, default: 'h5' }, size: { type: String, default: 'md' }, centered: { type: Boolean, default: false }, buttonSize: { type: String, default: '' }, noFade: { type: Boolean, default: false }, noCloseOnBackdrop: { type: Boolean, default: false }, noCloseOnEsc: { type: Boolean, default: false }, noEnforceFocus: { type: Boolean, default: false }, headerBgVariant: { type: String, default: null }, headerBorderVariant: { type: String, default: null }, headerTextVariant: { type: String, default: null }, headerClass: { type: [String, Array], default: null }, bodyBgVariant: { type: String, default: null }, bodyTextVariant: { type: String, default: null }, modalClass: { type: [String, Array], default: null }, bodyClass: { type: [String, Array], default: null }, footerBgVariant: { type: String, default: null }, footerBorderVariant: { type: String, default: null }, footerTextVariant: { type: String, default: null }, footerClass: { type: [String, Array], default: null }, hideHeader: { type: Boolean, default: false }, hideFooter: { type: Boolean, default: false }, hideHeaderClose: { type: Boolean, default: false }, hideBackdrop: { type: Boolean, default: false }, okOnly: { type: Boolean, default: false }, okDisabled: { type: Boolean, default: false }, cancelDisabled: { type: Boolean, default: false }, visible: { type: Boolean, default: false }, returnFocus: { default: null }, headerCloseLabel: { type: String, default: 'Close' }, cancelTitle: { type: String, default: 'Cancel' }, okTitle: { type: String, default: 'OK' }, cancelVariant: { type: String, default: 'secondary' }, okVariant: { type: String, default: 'primary' }, lazy: { type: Boolean, default: false }, busy: { type: Boolean, default: false } }, computed: { modalClasses: function modalClasses() { return ['modal', { fade: !this.noFade, show: this.is_show, 'd-block': this.is_block }, this.modalClass]; }, dialogClasses: function dialogClasses() { var _ref; return ['modal-dialog', (_ref = {}, defineProperty(_ref, 'modal-' + this.size, Boolean(this.size)), defineProperty(_ref, 'modal-dialog-centered', this.centered), _ref)]; }, backdropClasses: function backdropClasses() { return ['modal-backdrop', { fade: !this.noFade, show: this.is_show || this.noFade }]; }, headerClasses: function headerClasses() { var _ref2; return ['modal-header', (_ref2 = {}, defineProperty(_ref2, 'bg-' + this.headerBgVariant, Boolean(this.headerBgVariant)), defineProperty(_ref2, 'text-' + this.headerTextVariant, Boolean(this.headerTextVariant)), defineProperty(_ref2, 'border-' + this.headerBorderVariant, Boolean(this.headerBorderVariant)), _ref2), this.headerClass]; }, bodyClasses: function bodyClasses() { var _ref3; return ['modal-body', (_ref3 = {}, defineProperty(_ref3, 'bg-' + this.bodyBgVariant, Boolean(this.bodyBgVariant)), defineProperty(_ref3, 'text-' + this.bodyTextVariant, Boolean(this.bodyTextVariant)), _ref3), this.bodyClass]; }, footerClasses: function footerClasses() { var _ref4; return ['modal-footer', (_ref4 = {}, defineProperty(_ref4, 'bg-' + this.footerBgVariant, Boolean(this.footerBgVariant)), defineProperty(_ref4, 'text-' + this.footerTextVariant, Boolean(this.footerTextVariant)), defineProperty(_ref4, 'border-' + this.footerBorderVariant, Boolean(this.footerBorderVariant)), _ref4), this.footerClass]; } }, watch: { visible: function visible(newVal, oldVal) { if (newVal === oldVal) { return; } this[newVal ? 'show' : 'hide'](); } }, methods: { // Public Methods show: function show() { if (this.is_visible) { return; } var showEvt = new BvEvent('show', { cancelable: true, vueTarget: this, target: this.$refs.modal, relatedTarget: null }); this.emitEvent(showEvt); if (showEvt.defaultPrevented || this.is_visible) { // Don't show if canceled return; } if (hasClass(document.body, 'modal-open')) { // If another modal is already open, wait for it to close this.$root.$once('bv::modal::hidden', this.doShow); } else { // Show the modal this.doShow(); } }, hide: function hide(trigger) { if (!this.is_visible) { return; } var hideEvt = new BvEvent('hide', { cancelable: true, vueTarget: this, target: this.$refs.modal, // this could be the trigger element/component reference relatedTarget: null, isOK: trigger || null, trigger: trigger || null, cancel: function cancel() { // Backwards compatibility warn('b-modal: evt.cancel() is deprecated. Please use evt.preventDefault().'); this.preventDefault(); } }); if (trigger === 'ok') { this.$emit('ok', hideEvt); } else if (trigger === 'cancel') { this.$emit('cancel', hideEvt); } this.emitEvent(hideEvt); // Hide if not canceled if (hideEvt.defaultPrevented || !this.is_visible) { return; } // stop observing for content changes if (this._observer) { this._observer.disconnect(); this._observer = null; } this.is_visible = false; this.$emit('change', false); }, // Private method to finish showing modal doShow: function doShow() { var _this2 = this; // Plce modal in DOM if lazy this.is_hidden = false; this.$nextTick(function () { // We do this in nextTick to ensure the modal is in DOM first before we show it _this2.is_visible = true; _this2.$emit('change', true); // Observe changes in modal content and adjust if necessary _this2._observer = observeDOM(_this2.$refs.content, _this2.adjustDialog.bind(_this2), OBSERVER_CONFIG); }); }, // Transition Handlers onBeforeEnter: function onBeforeEnter() { this.is_transitioning = true; this.checkScrollbar(); this.setScrollbar(); this.adjustDialog(); addClass(document.body, 'modal-open'); this.setResizeEvent(true); }, onEnter: function onEnter() { this.is_block = true; this.$refs.modal.scrollTop = 0; }, onAfterEnter: function onAfterEnter() { var _this3 = this; this.is_show = true; this.is_transitioning = false; this.$nextTick(function () { _this3.focusFirst(); var shownEvt = new BvEvent('shown', { cancelable: false, vueTarget: _this3, target: _this3.$refs.modal, relatedTarget: null }); _this3.emitEvent(shownEvt); }); }, onBeforeLeave: function onBeforeLeave() { this.is_transitioning = true; this.setResizeEvent(false); }, onLeave: function onLeave() { // Remove the 'show' class this.is_show = false; }, onAfterLeave: function onAfterLeave() { var _this4 = this; this.is_block = false; this.resetAdjustments(); this.resetScrollbar(); this.is_transitioning = false; removeClass(document.body, 'modal-open'); this.$nextTick(function () { _this4.is_hidden = _this4.lazy || false; _this4.returnFocusTo(); var hiddenEvt = new BvEvent('hidden', { cancelable: false, vueTarget: _this4, target: _this4.lazy ? null : _this4.$refs.modal, relatedTarget: null }); _this4.emitEvent(hiddenEvt); }); }, // Event emitter emitEvent: function emitEvent(bvEvt) { var type = bvEvt.type; this.$emit(type, bvEvt); this.$root.$emit('bv::modal::' + type, bvEvt); }, // UI Event Handlers onClickOut: function onClickOut(evt) { // If backdrop clicked, hide modal if (this.is_visible && !this.noCloseOnBackdrop) { this.hide('backdrop'); } }, onEsc: function onEsc(evt) { // If ESC pressed, hide modal if (evt.keyCode === KeyCodes.ESC && this.is_visible && !this.noCloseOnEsc) { this.hide('esc'); } }, onFocusout: function onFocusout(evt) { // If focus leaves modal, bring it back // 'focusout' Event Listener bound on content var content = this.$refs.content; if (!this.noEnforceFocus && this.is_visible && content && !content.contains(evt.relatedTarget)) { content.focus(); } }, // Resize Listener setResizeEvent: function setResizeEvent(on) { var _this5 = this; ['resize', 'orientationchange'].forEach(function (evtName) { if (on) { eventOn(window, evtName, _this5.adjustDialog); } else { eventOff(window, evtName, _this5.adjustDialog); } }); }, // Root Listener handlers showHandler: function showHandler(id, triggerEl) { if (id === this.id) { this.return_focus = triggerEl || null; this.show(); } }, hideHandler: function hideHandler(id) { if (id === this.id) { this.hide(); } }, modalListener: function modalListener(bvEvt) { // If another modal opens, close this one if (bvEvt.vueTarget !== this) { this.hide(); } }, // Focus control handlers focusFirst: function focusFirst() { // Don't try and focus if we are SSR if (typeof document === 'undefined') { return; } var content = this.$refs.content; var modal = this.$refs.modal; var activeElement = document.activeElement; if (activeElement && content && content.contains(activeElement)) ; else if (content) { if (modal) { modal.scrollTop = 0; } // Focus the modal content wrapper content.focus(); } }, returnFocusTo: function returnFocusTo() { // Prefer returnFocus prop over event specified return_focus value var el = this.returnFocus || this.return_focus || null; if (typeof el === 'string') { // CSS Selector el = select(el); } if (el) { el = el.$el || el; if (isVisible(el)) { el.focus(); } } }, // Utility methods getScrollbarWidth: function getScrollbarWidth() { var scrollDiv = document.createElement('div'); scrollDiv.className = 'modal-scrollbar-measure'; document.body.appendChild(scrollDiv); this.scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; document.body.removeChild(scrollDiv); }, adjustDialog: function adjustDialog() { if (!this.is_visible) { return; } var modal = this.$refs.modal; var isModalOverflowing = modal.scrollHeight > document.documentElement.clientHeight; if (!this.isBodyOverflowing && isModalOverflowing) { modal.style.paddingLeft = this.scrollbarWidth + 'px'; } if (this.isBodyOverflowing && !isModalOverflowing) { modal.style.paddingRight = this.scrollbarWidth + 'px'; } }, resetAdjustments: function resetAdjustments() { var modal = this.$refs.modal; if (modal) { modal.style.paddingLeft = ''; modal.style.paddingRight = ''; } }, checkScrollbar: function checkScrollbar() { var rect = getBCR(document.body); this.isBodyOverflowing = rect.left + rect.right < window.innerWidth; }, setScrollbar: function setScrollbar() { if (this.isBodyOverflowing) { // Note: DOMNode.style.paddingRight returns the actual value or '' if not set // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set var computedStyle = window.getComputedStyle; var body = document.body; var scrollbarWidth = this.scrollbarWidth; // Adjust fixed content padding selectAll(Selector.FIXED_CONTENT).forEach(function (el) { var actualPadding = el.style.paddingRight; var calculatedPadding = computedStyle(el).paddingRight || 0; setAttr(el, 'data-padding-right', actualPadding); el.style.paddingRight = parseFloat(calculatedPadding) + scrollbarWidth + 'px'; }); // Adjust sticky content margin selectAll(Selector.STICKY_CONTENT).forEach(function (el) { var actualMargin = el.style.marginRight; var calculatedMargin = computedStyle(el).marginRight || 0; setAttr(el, 'data-margin-right', actualMargin); el.style.marginRight = parseFloat(calculatedMargin) - scrollbarWidth + 'px'; }); // Adjust navbar-toggler margin selectAll(Selector.NAVBAR_TOGGLER).forEach(function (el) { var actualMargin = el.style.marginRight; var calculatedMargin = computedStyle(el).marginRight || 0; setAttr(el, 'data-margin-right', actualMargin); el.style.marginRight = parseFloat(calculatedMargin) + scrollbarWidth + 'px'; }); // Adjust body padding var actualPadding = body.style.paddingRight; var calculatedPadding = computedStyle(body).paddingRight; setAttr(body, 'data-padding-right', actualPadding); body.style.paddingRight = parseFloat(calculatedPadding) + scrollbarWidth + 'px'; } }, resetScrollbar: function resetScrollbar() { // Restore fixed content padding selectAll(Selector.FIXED_CONTENT).forEach(function (el) { if (hasAttr(el, 'data-padding-right')) { el.style.paddingRight = getAttr(el, 'data-padding-right') || ''; removeAttr(el, 'data-padding-right'); } }); // Restore sticky content and navbar-toggler margin selectAll(Selector.STICKY_CONTENT + ', ' + Selector.NAVBAR_TOGGLER).forEach(function (el) { if (hasAttr(el, 'data-margin-right')) { el.style.marginRight = getAttr(el, 'data-margin-right') || ''; removeAttr(el, 'data-margin-right'); } }); // Restore body padding var body = document.body; if (hasAttr(body, 'data-padding-right')) { body.style.paddingRight = getAttr(body, 'data-padding-right') || ''; removeAttr(body, 'data-padding-right'); } } }, created: function created() { // create non-reactive property this._observer = null; }, mounted: function mounted() { // Measure scrollbar this.getScrollbarWidth(); // Listen for events from others to either open or close ourselves this.listenOnRoot('bv::show::modal', this.showHandler); this.listenOnRoot('bv::hide::modal', this.hideHandler); // Listen for bv:modal::show events, and close ourselves if the opening modal not us this.listenOnRoot('bv::modal::show', this.modalListener); // Initially show modal? if (this.visible === true) { this.show(); } }, beforeDestroy: function beforeDestroy() { // Ensure everything is back to normal if (this._observer) { this._observer.disconnect(); this._observer = null; } this.setResizeEvent(false); // Re-adjust body/navbar/fixed padding/margins (if needed) removeClass(document.body, 'modal-open'); this.resetAdjustments(); this.resetScrollbar(); } }; var listenTypes$1 = { click: true }; var bModal$1 = { // eslint-disable-next-line no-shadow-restricted-names bind: function bind(el, binding, vnode) { bindTargets(vnode, binding, listenTypes$1, function (_ref) { var targets = _ref.targets, vnode = _ref.vnode; targets.forEach(function (target) { vnode.context.$root.$emit('bv::show::modal', target, vnode.elm); }); }); if (el.tagName !== 'BUTTON') { // If element is not a button, we add `role="button"` for accessibility setAttr(el, 'role', 'button'); } }, unbind: function unbind(el, binding, vnode) { unbindTargets(vnode, binding, listenTypes$1); if (el.tagName !== 'BUTTON') { // If element is not a button, we add `role="button"` for accessibility removeAttr(el, 'role', 'button'); } } }; var directives$1 = { bModal: bModal$1 }; var VuePlugin$r = { install: function install(Vue) { registerDirectives(Vue, directives$1); } }; vueUse(VuePlugin$r); var components$q = { bModal: bModal }; var VuePlugin$s = { install: function install(Vue) { registerComponents(Vue, components$q); Vue.use(VuePlugin$r); } }; vueUse(VuePlugin$s); var props$A = { tag: { type: String, default: 'ul' }, fill: { type: Boolean, default: false }, justified: { type: Boolean, default: false }, tabs: { type: Boolean, default: false }, pills: { type: Boolean, default: false }, vertical: { type: Boolean, default: false }, isNavBar: { type: Boolean, default: false } }; var bNav = { functional: true, props: props$A, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; if (props.isNavBar) { warn("b-nav: Prop 'is-nav-bar' is deprecated. Please use component '' instead."); } return h(props.tag, mergeData(data, { class: { 'nav': !props.isNavBar, 'navbar-nav': props.isNavBar, 'nav-tabs': props.tabs && !props.isNavBar, 'nav-pills': props.pills && !props.isNavBar, 'flex-column': props.vertical && !props.isNavBar, 'nav-fill': props.fill, 'nav-justified': props.justified } }), children); } }; var props$B = propsFactory(); var bNavItem = { functional: true, props: props$B, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h('li', mergeData(data, { staticClass: 'nav-item' }), [h(bLink, { staticClass: 'nav-link', props: props }, children)]); } }; var props$C = { tag: { type: String, default: 'span' } }; var bNavText = { functional: true, props: props$C, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'navbar-text' }), children); } }; var bNavForm = { functional: true, props: { id: { type: String, default: null } }, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(Form, mergeData(data, { attrs: { id: props.id }, props: { inline: true } }), children); } }; var bNavItemDropdown = { mixins: [idMixin, dropdownMixin], render: function render(h) { var button = h('a', { class: this.toggleClasses, ref: 'toggle', attrs: { href: '#', id: this.safeId('_BV_button_'), disabled: this.disabled, 'aria-haspopup': 'true', 'aria-expanded': this.visible ? 'true' : 'false' }, on: { click: this.toggle, keydown: this.toggle // space, enter, down } }, [this.$slots['button-content'] || this.$slots.text || h('span', { domProps: { innerHTML: this.text } })]); var menu = h('div', { class: this.menuClasses, ref: 'menu', attrs: { 'aria-labelledby': this.safeId('_BV_button_') }, on: { mouseover: this.onMouseOver, keydown: this.onKeydown // tab, up, down, esc } }, [this.$slots.default]); return h('li', { attrs: { id: this.safeId() }, class: this.dropdownClasses }, [button, menu]); }, computed: { isNav: function isNav() { // Signal to dropdown mixin that we are in a navbar return true; }, dropdownClasses: function dropdownClasses() { return ['nav-item', 'b-nav-dropdown', 'dropdown', this.dropup ? 'dropup' : '', this.visible ? 'show' : '']; }, toggleClasses: function toggleClasses() { return ['nav-link', this.noCaret ? '' : 'dropdown-toggle', this.disabled ? 'disabled' : '', this.extraToggleClasses ? this.extraToggleClasses : '']; }, menuClasses: function menuClasses() { return ['dropdown-menu', this.right ? 'dropdown-menu-right' : 'dropdown-menu-left', this.visible ? 'show' : '', this.extraMenuClasses ? this.extraMenuClasses : '']; } }, props: { noCaret: { type: Boolean, default: false }, extraToggleClasses: { // Extra Toggle classes type: String, default: '' }, extraMenuClasses: { // Extra Menu classes type: String, default: '' }, role: { type: String, default: 'menu' } } }; var components$r = { bNav: bNav, bNavItem: bNavItem, bNavText: bNavText, bNavForm: bNavForm, bNavItemDropdown: bNavItemDropdown, bNavItemDd: bNavItemDropdown, bNavDropdown: bNavItemDropdown, bNavDd: bNavItemDropdown }; var VuePlugin$t = { install: function install(Vue) { registerComponents(Vue, components$r); Vue.use(VuePlugin$c); } }; vueUse(VuePlugin$t); var props$D = { tag: { type: String, default: 'nav' }, type: { type: String, default: 'light' }, variant: { type: String }, toggleable: { type: [Boolean, String], default: false }, toggleBreakpoint: { // Deprecated. Set toggleable to a string breakpoint type: String, default: null }, fixed: { type: String }, sticky: { type: Boolean, default: false } }; var bNavbar = { functional: true, props: props$D, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, children = _ref.children; var breakpoint = props.toggleBreakpoint || (props.toggleable === true ? 'sm' : props.toggleable) || 'sm'; return h(props.tag, mergeData(data, { staticClass: 'navbar', class: (_class = {}, defineProperty(_class, 'navbar-' + props.type, Boolean(props.type)), defineProperty(_class, 'bg-' + props.variant, Boolean(props.variant)), defineProperty(_class, 'fixed-' + props.fixed, Boolean(props.fixed)), defineProperty(_class, 'sticky-top', props.sticky), defineProperty(_class, 'navbar-expand-' + breakpoint, props.toggleable !== false), _class) }), children); } }; var props$E = { tag: { type: String, default: 'ul' }, fill: { type: Boolean, default: false }, justified: { type: Boolean, default: false } }; var bNavbarNav = { functional: true, props: props$E, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; return h(props.tag, mergeData(data, { staticClass: 'navbar-nav', class: { 'nav-fill': props.fill, 'nav-justified': props.justified } }), children); } }; var linkProps$3 = propsFactory(); linkProps$3.href.default = undefined; linkProps$3.to.default = undefined; var props$F = assign(linkProps$3, { tag: { type: String, default: 'div' } }); var bNavbarBrand = { functional: true, props: props$F, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var isLink = Boolean(props.to || props.href); var tag = isLink ? bLink : props.tag; return h(tag, mergeData(data, { staticClass: 'navbar-brand', props: isLink ? pluckProps(linkProps$3, props) : {} }), children); } }; var bNavbarToggle = { mixins: [listenOnRootMixin], render: function render(h) { return h('button', { class: ['navbar-toggler'], attrs: { type: 'button', 'aria-label': this.label, 'aria-controls': this.target, 'aria-expanded': this.toggleState ? 'true' : 'false' }, on: { click: this.onClick } }, [this.$slots.default || h('span', { class: ['navbar-toggler-icon'] })]); }, data: function data() { return { toggleState: false }; }, props: { label: { type: String, default: 'Toggle navigation' }, target: { type: String, required: true } }, methods: { onClick: function onClick() { this.$root.$emit('bv::toggle::collapse', this.target); }, handleStateEvt: function handleStateEvt(id, state) { if (id === this.target) { this.toggleState = state; } } }, created: function created() { this.listenOnRoot('bv::collapse::state', this.handleStateEvt); } }; var components$s = { bNavbar: bNavbar, bNavbarNav: bNavbarNav, bNavbarBrand: bNavbarBrand, bNavbarToggle: bNavbarToggle, bNavToggle: bNavbarToggle }; var VuePlugin$u = { install: function install(Vue) { registerComponents(Vue, components$s); Vue.use(VuePlugin$t); Vue.use(VuePlugin$b); Vue.use(VuePlugin$c); } }; vueUse(VuePlugin$u); /** * @param {number} length * @return {Array} */ var range = (function (length) { return Array.apply(null, { length: length }); }); /* * Comon props, computed, data, render function, and methods for b-pagination and b-pagination-nav */ // Make an array of N to N+X function makePageArray(startNum, numPages) { return range(numPages).map(function (value, index) { return { number: index + startNum, className: null }; }); } // Threshold of limit size when we start/stop showing ellipsis var ELLIPSIS_THRESHOLD = 3; // Props object var props$G = { disabled: { type: Boolean, default: false }, value: { type: Number, default: 1 }, limit: { type: Number, default: 5 }, size: { type: String, default: 'md' }, align: { type: String, default: 'left' }, hideGotoEndButtons: { type: Boolean, default: false }, ariaLabel: { type: String, default: 'Pagination' }, labelFirstPage: { type: String, default: 'Goto first page' }, firstText: { type: String, default: '«' }, labelPrevPage: { type: String, default: 'Goto previous page' }, prevText: { type: String, default: '‹' }, labelNextPage: { type: String, default: 'Goto next page' }, nextText: { type: String, default: '›' }, labelLastPage: { type: String, default: 'Goto last page' }, lastText: { type: String, default: '»' }, labelPage: { type: String, default: 'Goto page' }, hideEllipsis: { type: Boolean, default: false }, ellipsisText: { type: String, default: '…' } }; var paginationMixin = { components: { bLink: bLink }, data: function data() { return { showFirstDots: false, showLastDots: false, currentPage: this.value }; }, props: props$G, render: function render(h) { var _this = this; var buttons = []; // Factory function for prev/next/first/last buttons var makeEndBtns = function makeEndBtns(linkTo, ariaLabel, btnText, pageTest) { var button = void 0; pageTest = pageTest || linkTo; // Page # to test against to disable if (_this.disabled || _this.isActive(pageTest)) { button = h('li', { class: ['page-item', 'disabled'], attrs: { role: 'none presentation', 'aria-hidden': 'true' } }, [h('span', { class: ['page-link'], domProps: { innerHTML: btnText } })]); } else { button = h('li', { class: ['page-item'], attrs: { role: 'none presentation' } }, [h('b-link', { class: ['page-link'], props: _this.linkProps(linkTo), attrs: { role: 'menuitem', tabindex: '-1', 'aria-label': ariaLabel, 'aria-controls': _this.ariaControls || null }, on: { click: function click(evt) { _this.onClick(linkTo, evt); }, keydown: function keydown(evt) { // Links don't normally respond to SPACE, so we add that functionality if (evt.keyCode === KeyCodes.SPACE) { evt.preventDefault(); _this.onClick(linkTo, evt); } } } }, [h('span', { attrs: { 'aria-hidden': 'true' }, domProps: { innerHTML: btnText } })])]); } return button; }; // Ellipsis factory var makeEllipsis = function makeEllipsis() { return h('li', { class: ['page-item', 'disabled', 'd-none', 'd-sm-flex'], attrs: { role: 'separator' } }, [h('span', { class: ['page-link'], domProps: { innerHTML: _this.ellipsisText } })]); }; // Goto First Page button buttons.push(this.hideGotoEndButtons ? h(false) : makeEndBtns(1, this.labelFirstPage, this.firstText)); // Goto Previous page button buttons.push(makeEndBtns(this.currentPage - 1, this.labelPrevPage, this.prevText, 1)); // First Ellipsis Bookend buttons.push(this.showFirstDots ? makeEllipsis() : h(false)); // Individual Page links this.pageList.forEach(function (page) { var inner = void 0; var pageNum = _this.makePage(page.number); if (_this.disabled) { inner = h('span', { class: ['page-link'], domProps: { innerHTML: pageNum } }); } else { var active = _this.isActive(page.number); inner = h('b-link', { class: _this.pageLinkClasses(page), props: _this.linkProps(page.number), attrs: { role: 'menuitemradio', tabindex: active ? '0' : '-1', 'aria-controls': _this.ariaControls || null, 'aria-label': _this.labelPage + ' ' + page.number, 'aria-checked': active ? 'true' : 'false', 'aria-posinset': page.number, 'aria-setsize': _this.numberOfPages }, domProps: { innerHTML: pageNum }, on: { click: function click(evt) { _this.onClick(page.number, evt); }, keydown: function keydown(evt) { if (evt.keyCode === KeyCodes.SPACE) { evt.preventDefault(); _this.onClick(page.number, evt); } } } }); } buttons.push(h('li', { key: page.number, class: _this.pageItemClasses(page), attrs: { role: 'none presentation' } }, [inner])); }); // Last Ellipsis Bookend buttons.push(this.showLastDots ? makeEllipsis() : h(false)); // Goto Next page button buttons.push(makeEndBtns(this.currentPage + 1, this.labelNextPage, this.nextText, this.numberOfPages)); // Goto Last Page button buttons.push(this.hideGotoEndButtons ? h(false) : makeEndBtns(this.numberOfPages, this.labelLastPage, this.lastText)); // Assemble the paginatiom buttons var pagination = h('ul', { ref: 'ul', class: ['pagination', 'b-pagination', this.btnSize, this.alignment], attrs: { role: 'menubar', 'aria-disabled': this.disabled ? 'true' : 'false', 'aria-label': this.ariaLabel || null }, on: { keydown: function keydown(evt) { var keyCode = evt.keyCode; var shift = evt.shiftKey; if (keyCode === KeyCodes.LEFT) { evt.preventDefault(); shift ? _this.focusFirst() : _this.focusPrev(); } else if (keyCode === KeyCodes.RIGHT) { evt.preventDefault(); shift ? _this.focusLast() : _this.focusNext(); } } } }, buttons); // if we are pagination-nav, wrap in '