text: /*!
   * BootstrapVue 2.6.0
   *
   * @link https://bootstrap-vue.js.org
   * @source https://github.com/bootstrap-vue/bootstrap-vue
   * @copyright (c) 2016-2020 BootstrapVue
   * @license MIT
   * https://github.com/bootstrap-vue/bootstrap-vue/blob/master/LICENSE
   */
  
  (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('vue')) :
    typeof define === 'function' && define.amd ? define(['vue'], factory) :
    (global = global || self, global.bootstrapVue = factory(global.Vue));
  }(this, (function (Vue) { 'use strict';
  
    Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue;
  
    function _typeof(obj) {
      "@babel/helpers - typeof";
  
      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
        _typeof = function (obj) {
          return typeof obj;
        };
      } else {
        _typeof = function (obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
      }
  
      return _typeof(obj);
    }
  
    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a 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);
      }
    }
  
    function _createClass(Constructor, protoProps, staticProps) {
      if (protoProps) _defineProperties(Constructor.prototype, protoProps);
      if (staticProps) _defineProperties(Constructor, staticProps);
      return Constructor;
    }
  
    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;
    }
  
    function ownKeys(object, enumerableOnly) {
      var keys = Object.keys(object);
  
      if (Object.getOwnPropertySymbols) {
        var symbols = Object.getOwnPropertySymbols(object);
        if (enumerableOnly) symbols = symbols.filter(function (sym) {
          return Object.getOwnPropertyDescriptor(object, sym).enumerable;
        });
        keys.push.apply(keys, symbols);
      }
  
      return keys;
    }
  
    function _objectSpread2(target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i] != null ? arguments[i] : {};
  
        if (i % 2) {
          ownKeys(Object(source), true).forEach(function (key) {
            _defineProperty(target, key, source[key]);
          });
        } else if (Object.getOwnPropertyDescriptors) {
          Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
        } else {
          ownKeys(Object(source)).forEach(function (key) {
            Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
          });
        }
      }
  
      return target;
    }
  
    function _inherits(subClass, superClass) {
      if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function");
      }
  
      subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
          value: subClass,
          writable: true,
          configurable: true
        }
      });
      if (superClass) _setPrototypeOf(subClass, superClass);
    }
  
    function _getPrototypeOf(o) {
      _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
      };
      return _getPrototypeOf(o);
    }
  
    function _setPrototypeOf(o, p) {
      _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
        o.__proto__ = p;
        return o;
      };
  
      return _setPrototypeOf(o, p);
    }
  
    function isNativeReflectConstruct() {
      if (typeof Reflect === "undefined" || !Reflect.construct) return false;
      if (Reflect.construct.sham) return false;
      if (typeof Proxy === "function") return true;
  
      try {
        Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
        return true;
      } catch (e) {
        return false;
      }
    }
  
    function _construct(Parent, args, Class) {
      if (isNativeReflectConstruct()) {
        _construct = Reflect.construct;
      } else {
        _construct = function _construct(Parent, args, Class) {
          var a = [null];
          a.push.apply(a, args);
          var Constructor = Function.bind.apply(Parent, a);
          var instance = new Constructor();
          if (Class) _setPrototypeOf(instance, Class.prototype);
          return instance;
        };
      }
  
      return _construct.apply(null, arguments);
    }
  
    function _isNativeFunction(fn) {
      return Function.toString.call(fn).indexOf("[native code]") !== -1;
    }
  
    function _wrapNativeSuper(Class) {
      var _cache = typeof Map === "function" ? new Map() : undefined;
  
      _wrapNativeSuper = function _wrapNativeSuper(Class) {
        if (Class === null || !_isNativeFunction(Class)) return Class;
  
        if (typeof Class !== "function") {
          throw new TypeError("Super expression must either be null or a function");
        }
  
        if (typeof _cache !== "undefined") {
          if (_cache.has(Class)) return _cache.get(Class);
  
          _cache.set(Class, Wrapper);
        }
  
        function Wrapper() {
          return _construct(Class, arguments, _getPrototypeOf(this).constructor);
        }
  
        Wrapper.prototype = Object.create(Class.prototype, {
          constructor: {
            value: Wrapper,
            enumerable: false,
            writable: true,
            configurable: true
          }
        });
        return _setPrototypeOf(Wrapper, Class);
      };
  
      return _wrapNativeSuper(Class);
    }
  
    function _assertThisInitialized(self) {
      if (self === void 0) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
      }
  
      return self;
    }
  
    function _possibleConstructorReturn(self, call) {
      if (call && (typeof call === "object" || typeof call === "function")) {
        return call;
      }
  
      return _assertThisInitialized(self);
    }
  
    function _superPropBase(object, property) {
      while (!Object.prototype.hasOwnProperty.call(object, property)) {
        object = _getPrototypeOf(object);
        if (object === null) break;
      }
  
      return object;
    }
  
    function _get(target, property, receiver) {
      if (typeof Reflect !== "undefined" && Reflect.get) {
        _get = Reflect.get;
      } else {
        _get = function _get(target, property, receiver) {
          var base = _superPropBase(target, property);
  
          if (!base) return;
          var desc = Object.getOwnPropertyDescriptor(base, property);
  
          if (desc.get) {
            return desc.get.call(receiver);
          }
  
          return desc.value;
        };
      }
  
      return _get(target, property, receiver || target);
    }
  
    function _slicedToArray(arr, i) {
      return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
    }
  
    function _toConsumableArray(arr) {
      return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
    }
  
    function _arrayWithoutHoles(arr) {
      if (Array.isArray(arr)) {
        for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
  
        return arr2;
      }
    }
  
    function _arrayWithHoles(arr) {
      if (Array.isArray(arr)) return arr;
    }
  
    function _iterableToArray(iter) {
      if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
    }
  
    function _iterableToArrayLimit(arr, i) {
      if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
        return;
      }
  
      var _arr = [];
      var _n = true;
      var _d = false;
      var _e = undefined;
  
      try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);
  
          if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;
        _e = err;
      } finally {
        try {
          if (!_n && _i["return"] != null) _i["return"]();
        } finally {
          if (_d) throw _e;
        }
      }
  
      return _arr;
    }
  
    function _nonIterableSpread() {
      throw new TypeError("Invalid attempt to spread non-iterable instance");
    }
  
    function _nonIterableRest() {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  
    //
  
    // --- Static ---
    var from = function from() {
      return Array.from.apply(Array, arguments);
    };
    var isArray = function isArray(val) {
      return Array.isArray(val);
    }; // --- Instance ---
  
    var arrayIncludes = function arrayIncludes(array, value) {
      return array.indexOf(value) !== -1;
    };
    var concat = function concat() {
      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
  
      return Array.prototype.concat.apply([], args);
    };
  
    var assign = function assign() {
      return Object.assign.apply(Object, arguments);
    };
    var create = function create(proto, optionalProps) {
      return Object.create(proto, optionalProps);
    };
    var defineProperties = function defineProperties(obj, props) {
      return Object.defineProperties(obj, props);
    };
    var defineProperty = function defineProperty(obj, prop, descr) {
      return Object.defineProperty(obj, prop, descr);
    };
    var freeze = function freeze(obj) {
      return Object.freeze(obj);
    };
    var getOwnPropertyNames = function getOwnPropertyNames(obj) {
      return Object.getOwnPropertyNames(obj);
    };
    var keys = function keys(obj) {
      return Object.keys(obj);
    }; // --- "Instance" ---
  
    var hasOwnProperty = function hasOwnProperty(obj, prop) {
      return Object.prototype.hasOwnProperty.call(obj, prop);
    };
    var toString = function toString(obj) {
      return Object.prototype.toString.call(obj);
    }; // --- Utilities ---
  
    /**
     * Quick object check - this is primarily used to tell
     * Objects from primitive values when we know the value
     * is a JSON-compliant type.
     * Note object could be a complex type like array, date, etc.
     */
  
    var isObject = function isObject(obj) {
      return obj !== null && _typeof(obj) === 'object';
    };
    /**
     * Strict object type check. Only returns true
     * for plain JavaScript objects.
     */
  
    var isPlainObject = function isPlainObject(obj) {
      return Object.prototype.toString.call(obj) === '[object Object]';
    };
    /**
     * Shallow copy an object. If the passed in object
     * is null or undefined, returns an empty object
     */
  
    var clone = function clone(obj) {
      return _objectSpread2({}, obj);
    };
    /**
     * Return a shallow copy of object with
     * the specified properties omitted
     * @link https://gist.github.com/bisubus/2da8af7e801ffd813fab7ac221aa7afc
     */
  
    var omit = function omit(obj, props) {
      return keys(obj).filter(function (key) {
        return props.indexOf(key) === -1;
      }).reduce(function (result, key) {
        return _objectSpread2({}, result, _defineProperty({}, key, obj[key]));
      }, {});
    };
    /**
     * Convenience method to create a read-only descriptor
     */
  
    var readonlyDescriptor = function readonlyDescriptor() {
      return {
        enumerable: true,
        configurable: false,
        writable: false
      };
    };
    /**
     * Deep-freezes and object, making it immutable / read-only.
     * Returns the same object passed-in, but frozen.
     * Freezes inner object/array/values first.
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
     * Note: this method will not work for property values using Symbol() as a key
     */
  
    var deepFreeze = function deepFreeze(obj) {
      // Retrieve the property names defined on object/array
      // Note: `keys` will ignore properties that are keyed by a `Symbol()`
      var props = keys(obj); // Iterate over each prop and recursively freeze it
  
      props.forEach(function (prop) {
        var value = obj[prop]; // If value is a plain object or array, we deepFreeze it
  
        obj[prop] = value && (isPlainObject(value) || isArray(value)) ? deepFreeze(value) : value;
      });
      return freeze(obj);
    };
  
    /**
     * Utilities to get information about the current environment
     */
    // --- Constants ---
    var hasWindowSupport = typeof window !== 'undefined';
    var hasDocumentSupport = typeof document !== 'undefined';
    var hasNavigatorSupport = typeof navigator !== 'undefined';
    var hasPromiseSupport = typeof Promise !== 'undefined';
    var hasMutationObserverSupport = typeof MutationObserver !== 'undefined' || typeof WebKitMutationObserver !== 'undefined' || typeof MozMutationObserver !== 'undefined';
    var isBrowser = hasWindowSupport && hasDocumentSupport && hasNavigatorSupport; // Browser type sniffing
  
    var userAgent = isBrowser ? window.navigator.userAgent.toLowerCase() : '';
    var isJSDOM = userAgent.indexOf('jsdom') > 0;
    var isIE = /msie|trident/.test(userAgent); // Determine if the browser supports the option passive for events
  
    var hasPassiveEventSupport = function () {
      var passiveEventSupported = false;
  
      if (isBrowser) {
        try {
          var options = {
            get passive() {
              // This function will be called when the browser
              // attempts to access the passive property.
  
              /* istanbul ignore next: will never be called in JSDOM */
              passiveEventSupported = true;
            }
  
          };
          window.addEventListener('test', options, options);
          window.removeEventListener('test', options, options);
        } catch (err) {
          /* istanbul ignore next: will never be called in JSDOM */
          passiveEventSupported = false;
        }
      }
  
      return passiveEventSupported;
    }();
    var hasTouchSupport = isBrowser && ('ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0);
    var hasPointerEventSupport = isBrowser && Boolean(window.PointerEvent || window.MSPointerEvent);
    var hasIntersectionObserverSupport = isBrowser && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && // Edge 15 and UC Browser lack support for `isIntersecting`
    // but we an use intersectionRatio > 0 instead
    // 'isIntersecting' in window.IntersectionObserverEntry.prototype &&
    'intersectionRatio' in window.IntersectionObserverEntry.prototype; // --- Getters ---
  
    var getEnv = function getEnv(key) {
      var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      var env = typeof process !== 'undefined' && process ? process.env || {} : {};
  
      if (!key) {
        /* istanbul ignore next */
        return env;
      }
  
      return env[key] || fallback;
    };
    var getNoWarn = function getNoWarn() {
      return getEnv('BOOTSTRAP_VUE_NO_WARN');
    };
  
    var w = hasWindowSupport ? window : {};
    var Element$1 = hasWindowSupport ? w.Element : /*#__PURE__*/function (_Object) {
      _inherits(Element, _Object);
  
      function Element() {
        _classCallCheck(this, Element);
  
        return _possibleConstructorReturn(this, _getPrototypeOf(Element).apply(this, arguments));
      }
  
      return Element;
    }( /*#__PURE__*/_wrapNativeSuper(Object));
    var HTMLElement = hasWindowSupport ? w.HTMLElement : /*#__PURE__*/function (_Element) {
      _inherits(HTMLElement, _Element);
  
      function HTMLElement() {
        _classCallCheck(this, HTMLElement);
  
        return _possibleConstructorReturn(this, _getPrototypeOf(HTMLElement).apply(this, arguments));
      }
  
      return HTMLElement;
    }(Element$1);
    var SVGElement = hasWindowSupport ? w.SVGElement : /*#__PURE__*/function (_Element2) {
      _inherits(SVGElement, _Element2);
  
      function SVGElement() {
        _classCallCheck(this, SVGElement);
  
        return _possibleConstructorReturn(this, _getPrototypeOf(SVGElement).apply(this, arguments));
      }
  
      return SVGElement;
    }(Element$1);
    var File = hasWindowSupport ? w.File : /*#__PURE__*/function (_Object2) {
      _inherits(File, _Object2);
  
      function File() {
        _classCallCheck(this, File);
  
        return _possibleConstructorReturn(this, _getPrototypeOf(File).apply(this, arguments));
      }
  
      return File;
    }( /*#__PURE__*/_wrapNativeSuper(Object));
  
    var toType = function toType(val) {
      return _typeof(val);
    };
    var toRawType = function toRawType(val) {
      return Object.prototype.toString.call(val).slice(8, -1);
    };
    var isUndefined = function isUndefined(val) {
      return val === undefined;
    };
    var isNull = function isNull(val) {
      return val === null;
    };
    var isUndefinedOrNull = function isUndefinedOrNull(val) {
      return isUndefined(val) || isNull(val);
    };
    var isFunction = function isFunction(val) {
      return toType(val) === 'function';
    };
    var isBoolean = function isBoolean(val) {
      return toType(val) === 'boolean';
    };
    var isString = function isString(val) {
      return toType(val) === 'string';
    };
    var isNumber = function isNumber(val) {
      return toType(val) === 'number';
    };
    var isDate = function isDate(val) {
      return val instanceof Date;
    };
    var isEvent = function isEvent(val) {
      return val instanceof Event;
    };
    var isFile = function isFile(val) {
      return val instanceof File;
    };
    var isRegExp = function isRegExp(val) {
      return toRawType(val) === 'RegExp';
    };
    var isPromise = function isPromise(val) {
      return !isUndefinedOrNull(val) && isFunction(val.then) && isFunction(val.catch);
    }; // Extra convenience named re-exports
  
    var cloneDeep = function cloneDeep(obj) {
      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : obj;
  
      if (isArray(obj)) {
        return obj.reduce(function (result, val) {
          return [].concat(_toConsumableArray(result), [cloneDeep(val, val)]);
        }, []);
      }
  
      if (isPlainObject(obj)) {
        return keys(obj).reduce(function (result, key) {
          return _objectSpread2({}, result, _defineProperty({}, key, cloneDeep(obj[key], obj[key])));
        }, {});
      }
  
      return defaultValue;
    };
  
    var identity = function identity(x) {
      return x;
    };
  
    var RX_ARRAY_NOTATION = /\[(\d+)]/g;
    /**
     * Get property defined by dot/array notation in string.
     *
     * @link https://gist.github.com/jeneg/9767afdcca45601ea44930ea03e0febf#gistcomment-1935901
     *
     * @param {Object} obj
     * @param {string|Array} path
     * @param {*} defaultValue (optional)
     * @return {*}
     */
  
    var get = function get(obj, path) {
      var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      // Handle array of path values
      path = isArray(path) ? path.join('.') : path; // If no path or no object passed
  
      if (!path || !isObject(obj)) {
        return defaultValue;
      } // Handle edge case where user has dot(s) in top-level item field key
      // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2762
      // Switched to `in` operator vs `hasOwnProperty` to handle obj.prototype getters
      // https://github.com/bootstrap-vue/bootstrap-vue/issues/3463
  
  
      if (path in obj) {
        return obj[path];
      } // Handle string array notation (numeric indices only)
  
  
      path = String(path).replace(RX_ARRAY_NOTATION, '.$1');
      var steps = path.split('.').filter(identity); // Handle case where someone passes a string of only dots
  
      if (steps.length === 0) {
        return defaultValue;
      } // Traverse path in object to find result
      // We use `!=` vs `!==` to test for both `null` and `undefined`
      // Switched to `in` operator vs `hasOwnProperty` to handle obj.prototype getters
      // https://github.com/bootstrap-vue/bootstrap-vue/issues/3463
  
  
      return steps.every(function (step) {
        return isObject(obj) && step in obj && (obj = obj[step]) != null;
      }) ? obj : defaultValue;
    };
  
    /**
     * Log a warning message to the console with BootstrapVue formatting
     * @param {string} message
     */
  
    var warn = function warn(message)
    /* istanbul ignore next */
    {
      var source = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  
      if (!getNoWarn()) {
        console.warn("[BootstrapVue warn]: ".concat(source ? "".concat(source, " - ") : '').concat(message));
      }
    };
    /**
     * Warn when no Promise support is given
     * @param {string} source
     * @returns {boolean} warned
     */
  
    var warnNotClient = function warnNotClient(source) {
      /* istanbul ignore else */
      if (isBrowser) {
        return false;
      } else {
        warn("".concat(source, ": Can not be called during SSR."));
        return true;
      }
    };
    /**
     * Warn when no Promise support is given
     * @param {string} source
     * @returns {boolean} warned
     */
  
    var warnNoPromiseSupport = function warnNoPromiseSupport(source) {
      /* istanbul ignore else */
      if (hasPromiseSupport) {
        return false;
      } else {
        warn("".concat(source, ": Requires Promise support."));
        return true;
      }
    };
    /**
     * Warn when no MutationObserver support is given
     * @param {string} source
     * @returns {boolean} warned
     */
  
    var warnNoMutationObserverSupport = function warnNoMutationObserverSupport(source) {
      /* istanbul ignore else */
      if (hasMutationObserverSupport) {
        return false;
      } else {
        warn("".concat(source, ": Requires MutationObserver support."));
        return true;
      }
    };
  
    // NOTES
    //
    // The global config SHALL NOT be used to set defaults for Boolean props, as the props
    // would loose their semantic meaning, and force people writing 3rd party components to
    // explicity set a true or false value using the v-bind syntax on boolean props
    //
    // Supported config values (depending on the prop's supported type(s)):
    // `String`, `Array`, `Object`, `null` or `undefined`
    // BREAKPOINT DEFINITIONS
    //
    // Some components (`<b-col>` and `<b-form-group>`) generate props based on breakpoints,
    // and this occurs when the component is first loaded (evaluated), which may happen
    // before the config is created/modified
    //
    // To get around this we make these components' props async (lazy evaluation)
    // The component definition is only called/executed when the first access to the
    // component is used (and cached on subsequent uses)
    // PROP DEFAULTS
    //
    // For default values on props, we use the default value factory function approach so
    // that the default values are pulled in at each component instantiation
    //
    //  props: {
    //    variant: {
    //      type: String,
    //      default: () => getConfigComponent('BAlert', 'variant')
    //    }
    //  }
    //
    // We also provide a cached getter for breakpoints, which are "frozen" on first access
    // prettier-ignore
  
    var DEFAULTS = deepFreeze({
      // Breakpoints
      breakpoints: ['xs', 'sm', 'md', 'lg', 'xl'],
      // Form controls
      formControls: {
        size: null
      },
      // Component specific defaults are keyed by the component
      // name (PascalCase) and prop name (camelCase)
      BAlert: {
        dismissLabel: 'Close',
        variant: 'info'
      },
      BBadge: {
        variant: 'secondary'
      },
      BButton: {
        size: null,
        variant: 'secondary'
      },
      BButtonClose: {
        content: '&times;',
        // `textVariant` is `null` to inherit the current text color
        textVariant: null,
        ariaLabel: 'Close'
      },
      BCalendar: {
        // BFormDate will choose these first if not provided in BFormDate section
        labelPrevYear: 'Previous year',
        labelPrevMonth: 'Previous month',
        labelCurrentMonth: 'Current month',
        labelNextMonth: 'Next month',
        labelNextYear: 'Next year',
        labelToday: 'Today',
        labelSelected: 'Selected date',
        labelNoDateSelected: 'No date selected',
        labelCalendar: 'Calendar',
        labelNav: 'Calendar navigation',
        labelHelp: 'Use cursor keys to navigate calendar dates'
      },
      BCardSubTitle: {
        // `<b-card>` and `<b-card-body>` also inherit this prop
        subTitleTextVariant: 'muted'
      },
      BCarousel: {
        labelPrev: 'Previous Slide',
        labelNext: 'Next Slide',
        labelGotoSlide: 'Goto Slide',
        labelIndicators: 'Select a slide to display'
      },
      BDropdown: {
        toggleText: 'Toggle Dropdown',
        size: null,
        variant: 'secondary',
        splitVariant: null
      },
      BFormDatepicker: {
        // BFormDatepicker will choose from BCalendar first if not provided here
        labelPrevYear: null,
        labelPrevMonth: null,
        labelCurrentMonth: null,
        labelNextMonth: null,
        labelNextYear: null,
        labelToday: null,
        labelSelected: null,
        labelNoDateSelected: null,
        labelCalendar: null,
        labelNav: null,
        labelHelp: null,
        // These props are specific to BFormDatepicker
        labelTodayButton: 'Select today',
        labelResetButton: 'Reset',
        labelCloseButton: 'Close'
      },
      BFormFile: {
        browseText: 'Browse',
        // Chrome default file prompt
        placeholder: 'No file chosen',
        dropPlaceholder: 'Drop files here'
      },
      BFormTag: {
        removeLabel: 'Remove tag',
        variant: 'secondary'
      },
      BFormTags: {
        addButtonText: 'Add',
        addButtonVariant: 'outline-secondary',
        duplicateTagText: 'Duplicate tag(s)',
        invalidTagText: 'Invalid tag(s)',
        placeholder: 'Add tag...',
        tagRemoveLabel: 'Remove tag',
        tagRemovedLabel: 'Tag removed',
        tagVariant: 'secondary'
      },
      BFormText: {
        textVariant: 'muted'
      },
      BFormTimepicker: {
        // Fallback to BTime
        labelNoTimeSelected: null,
        labelSelected: null,
        labelHours: null,
        labelMinutes: null,
        labelSeconds: null,
        labelAmpm: null,
        labelAm: null,
        labelPm: null,
        // Fallback to BTime then BFormSpinbutton
        labelDecrement: null,
        labelIncrement: null,
        // These props are specific to BFormTimepicker
        labelNowButton: 'Select now',
        labelResetButton: 'Reset',
        labelCloseButton: 'Close'
      },
      BFormSpinbutton: {
        labelDecrement: 'Decrement',
        labelIncrement: 'Increment'
      },
      BImg: {
        blankColor: 'transparent'
      },
      BImgLazy: {
        blankColor: 'transparent'
      },
      BInputGroup: {
        size: null
      },
      BJumbotron: {
        bgVariant: null,
        borderVariant: null,
        textVariant: null
      },
      BListGroupItem: {
        variant: null
      },
      BModal: {
        titleTag: 'h5',
        size: 'md',
        headerBgVariant: null,
        headerBorderVariant: null,
        headerTextVariant: null,
        headerCloseVariant: null,
        bodyBgVariant: null,
        bodyTextVariant: null,
        footerBgVariant: null,
        footerBorderVariant: null,
        footerTextVariant: null,
        cancelTitle: 'Cancel',
        cancelVariant: 'secondary',
        okTitle: 'OK',
        okVariant: 'primary',
        headerCloseContent: '&times;',
        headerCloseLabel: 'Close'
      },
      BNavbar: {
        variant: null
      },
      BNavbarToggle: {
        label: 'Toggle navigation'
      },
      BPagination: {
        size: null
      },
      BPaginationNav: {
        size: null
      },
      BPopover: {
        boundary: 'scrollParent',
        boundaryPadding: 5,
        customClass: null,
        delay: 50,
        variant: null
      },
      BProgress: {
        variant: null
      },
      BProgressBar: {
        variant: null
      },
      BSpinner: {
        variant: null
      },
      BTable: {
        selectedVariant: 'active',
        headVariant: null,
        footVariant: null
      },
      BTime: {
        labelNoTimeSelected: 'No time selected',
        labelSelected: 'Selected time',
        labelHours: 'Hours',
        labelMinutes: 'Minutes',
        labelSeconds: 'Seconds',
        labelAmpm: 'AM/PM',
        // It would be nice to be able to get these from Intl.DateTimeFormat somehow
        labelAm: 'AM',
        labelPm: 'PM',
        // The following inherit from BFormSpinbutton if not provided
        labelIncrement: null,
        labelDecrement: null
      },
      BToast: {
        toaster: 'b-toaster-top-right',
        autoHideDelay: 5000,
        variant: null,
        toastClass: null,
        headerClass: null,
        bodyClass: null
      },
      BToaster: {
        ariaLive: null,
        ariaAtomic: null,
        role: null
      },
      BTooltip: {
        boundary: 'scrollParent',
        boundaryPadding: 5,
        customClass: null,
        delay: 50,
        variant: null
      }
    });
  
    var NAME = 'BvConfig';
    var PROP_NAME = '$bvConfig'; // Config manager class
  
    var BvConfig = /*#__PURE__*/function () {
      function BvConfig() {
        _classCallCheck(this, BvConfig);
  
        // TODO: pre-populate with default config values (needs updated tests)
        // this.$_config = cloneDeep(DEFAULTS)
        this.$_config = {};
        this.$_cachedBreakpoints = null;
      }
  
      _createClass(BvConfig, [{
        key: "getDefaults",
        // Returns the defaults
        value: function getDefaults()
        /* istanbul ignore next */
        {
          return this.defaults;
        } // Method to merge in user config parameters
  
      }, {
        key: "setConfig",
        value: function setConfig() {
          var _this = this;
  
          var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  
          if (!isPlainObject(config)) {
            /* istanbul ignore next */
            return;
          }
  
          var configKeys = getOwnPropertyNames(config);
          configKeys.forEach(function (cmpName) {
            /* istanbul ignore next */
            if (!hasOwnProperty(DEFAULTS, cmpName)) {
              warn("Unknown config property \"".concat(cmpName, "\""), NAME);
              return;
            }
  
            var cmpConfig = config[cmpName];
  
            if (cmpName === 'breakpoints') {
              // Special case for breakpoints
              var breakpoints = config.breakpoints;
              /* istanbul ignore if */
  
              if (!isArray(breakpoints) || breakpoints.length < 2 || breakpoints.some(function (b) {
                return !isString(b) || b.length === 0;
              })) {
                warn('"breakpoints" must be an array of at least 2 breakpoint names', NAME);
              } else {
                _this.$_config.breakpoints = cloneDeep(breakpoints);
              }
            } else if (isPlainObject(cmpConfig)) {
              // Component prop defaults
              var props = getOwnPropertyNames(cmpConfig);
              props.forEach(function (prop) {
                /* istanbul ignore if */
                if (!hasOwnProperty(DEFAULTS[cmpName], prop)) {
                  warn("Unknown config property \"".concat(cmpName, ".").concat(prop, "\""), NAME);
                } else {
                  // TODO: If we pre-populate the config with defaults, we can skip this line
                  _this.$_config[cmpName] = _this.$_config[cmpName] || {};
  
                  if (!isUndefined(cmpConfig[prop])) {
                    _this.$_config[cmpName][prop] = cloneDeep(cmpConfig[prop]);
                  }
                }
              });
            }
          });
        } // Clear the config. For testing purposes only
  
      }, {
        key: "resetConfig",
        value: function resetConfig() {
          this.$_config = {};
        } // Returns a deep copy of the user config
  
      }, {
        key: "getConfig",
        value: function getConfig() {
          return cloneDeep(this.$_config);
        }
      }, {
        key: "getConfigValue",
        value: function getConfigValue(key) {
          // First we try the user config, and if key not found we fall back to default value
          // NOTE: If we deep clone DEFAULTS into config, then we can skip the fallback for get
          return cloneDeep(get(this.$_config, key, get(DEFAULTS, key)));
        }
      }, {
        key: "defaults",
        get: function get()
        /* istanbul ignore next */
        {
          return DEFAULTS;
        }
      }], [{
        key: "Defaults",
        get: function get()
        /* istanbul ignore next */
        {
          return DEFAULTS;
        }
      }]);
  
      return BvConfig;
    }(); // Method for applying a global config
  
  
    var setConfig = function setConfig() {
      var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var Vue$1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Vue;
      // Ensure we have a $bvConfig Object on the Vue prototype.
      // We set on Vue and OurVue just in case consumer has not set an alias of `vue`.
      Vue$1.prototype[PROP_NAME] = Vue.prototype[PROP_NAME] = Vue$1.prototype[PROP_NAME] || Vue.prototype[PROP_NAME] || new BvConfig(); // Apply the config values
  
      Vue$1.prototype[PROP_NAME].setConfig(config);
    }; // Method for resetting the user config. Exported for testing purposes only.
  
    /**
     * Checks if there are multiple instances of Vue, and warns (once) about possible issues.
     * @param {object} Vue
     */
  
    var checkMultipleVue = function () {
      var checkMultipleVueWarned = false;
      var MULTIPLE_VUE_WARNING = ['Multiple instances of Vue detected!', 'You may need to set up an alias for Vue in your bundler config.', 'See: https://bootstrap-vue.js.org/docs#using-module-bundlers'].join('\n');
      return function (Vue$1) {
        /* istanbul ignore next */
        if (!checkMultipleVueWarned && Vue !== Vue$1 && !isJSDOM) {
          warn(MULTIPLE_VUE_WARNING);
        }
  
        checkMultipleVueWarned = true;
      };
    }();
    /**
     * Plugin install factory function.
     * @param {object} { components, directives }
     * @returns {function} plugin install function
     */
  
    var installFactory = function installFactory() {
      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
          components = _ref.components,
          directives = _ref.directives,
          plugins = _ref.plugins;
  
      var install = function install(Vue) {
        var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
        if (install.installed) {
          /* istanbul ignore next */
          return;
        }
  
        install.installed = true;
        checkMultipleVue(Vue);
        setConfig(config, Vue);
        registerComponents(Vue, components);
        registerDirectives(Vue, directives);
        registerPlugins(Vue, plugins);
      };
  
      install.installed = false;
      return install;
    };
    /**
     * Plugin object factory function.
     * @param {object} { components, directives, plugins }
     * @returns {object} plugin install object
     */
  
    var pluginFactory = function pluginFactory() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var extend = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      return _objectSpread2({}, extend, {
        install: installFactory(options)
      });
    };
    /**
     * Load a group of plugins.
     * @param {object} Vue
     * @param {object} Plugin definitions
     */
  
    var registerPlugins = function registerPlugins(Vue) {
      var plugins = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
      for (var plugin in plugins) {
        if (plugin && plugins[plugin]) {
          Vue.use(plugins[plugin]);
        }
      }
    };
    /**
     * Load a component.
     * @param {object} Vue
     * @param {string} Component name
     * @param {object} Component definition
     */
  
    var registerComponent = function registerComponent(Vue, name, def) {
      if (Vue && name && def) {
        Vue.component(name, def);
      }
    };
    /**
     * Load a group of components.
     * @param {object} Vue
     * @param {object} Object of component definitions
     */
  
    var registerComponents = function registerComponents(Vue) {
      var components = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
      for (var component in components) {
        registerComponent(Vue, component, components[component]);
      }
    };
    /**
     * Load a directive.
     * @param {object} Vue
     * @param {string} Directive name
     * @param {object} Directive definition
     */
  
    var registerDirective = function registerDirective(Vue, name, def) {
      if (Vue && name && def) {
        // Ensure that any leading V is removed from the
        // name, as Vue adds it automatically
        Vue.directive(name.replace(/^VB/, 'B'), def);
      }
    };
    /**
     * Load a group of directives.
     * @param {object} Vue
     * @param {object} Object of directive definitions
     */
  
    var registerDirectives = function registerDirectives(Vue) {
      var directives = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
      for (var directive in directives) {
        registerDirective(Vue, directive, directives[directive]);
      }
    };
    /**
     * Install plugin if window.Vue available
     * @param {object} Plugin definition
     */
  
    var vueUse = function vueUse(VuePlugin) {
      /* istanbul ignore next */
      if (hasWindowSupport && window.Vue) {
        window.Vue.use(VuePlugin);
      }
      /* istanbul ignore next */
  
  
      if (hasWindowSupport && VuePlugin.NAME) {
        window[VuePlugin.NAME] = VuePlugin;
      }
    };
  
    var memoize = function memoize(fn) {
      var cache = create(null);
      return function () {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }
  
        var argsKey = JSON.stringify(args);
        return cache[argsKey] = cache[argsKey] || fn.apply(null, args);
      };
    };
  
    var PROP_NAME$1 = '$bvConfig';
    var VueProto = Vue.prototype; // --- Getter methods ---
  
    var getConfigValue = function getConfigValue(key) {
      return VueProto[PROP_NAME$1] ? VueProto[PROP_NAME$1].getConfigValue(key) : cloneDeep(get(DEFAULTS, key));
    }; // Method to grab a config value for a particular component
  
    var getComponentConfig = function getComponentConfig(cmpName) {
      var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      // Return the particular config value for key for if specified,
      // otherwise we return the full config (or an empty object if not found)
      return key ? getConfigValue("".concat(cmpName, ".").concat(key)) : getConfigValue(cmpName) || {};
    }; // Convenience method for getting all breakpoint names
  
    var getBreakpoints = function getBreakpoints() {
      return getConfigValue('breakpoints');
    }; // Private function for caching / locking-in breakpoint names
  
    var _getBreakpointsCached = memoize(function () {
      return getBreakpoints();
    }); // Convenience method for getting all breakpoint names.
    // Caches the results after first access.
  
  
    var getBreakpointsCached = function getBreakpointsCached() {
      return cloneDeep(_getBreakpointsCached());
    }; // Convenience method for getting breakpoints with
    // the smallest breakpoint set as ''.
    // Useful for components that create breakpoint specific props.
    // Caches the results after first access.
  
    var getBreakpointsUpCached = memoize(function () {
      var breakpoints = getBreakpointsCached();
      breakpoints[0] = '';
      return breakpoints;
    }); // Convenience method for getting breakpoints with
  
    var w$1 = hasWindowSupport ? window : {};
    var d = hasDocumentSupport ? document : {};
    var elProto = typeof Element !== 'undefined' ? Element.prototype : {}; // --- Normalization utils ---
    // See: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
  
    /* istanbul ignore next */
  
    var matchesEl = elProto.matches || elProto.msMatchesSelector || elProto.webkitMatchesSelector; // See: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
  
    /* istanbul ignore next */
  
    var closestEl = elProto.closest || function (sel)
    /* istanbul ignore next */
    {
      var el = this;
  
      do {
        // Use our "patched" matches function
        if (matches(el, sel)) {
          return el;
        }
  
        el = el.parentElement || el.parentNode;
      } while (!isNull(el) && el.nodeType === Node.ELEMENT_NODE);
  
      return null;
    }; // `requestAnimationFrame()` convenience method
  
    var requestAF = w$1.requestAnimationFrame || w$1.webkitRequestAnimationFrame || w$1.mozRequestAnimationFrame || w$1.msRequestAnimationFrame || w$1.oRequestAnimationFrame || // Fallback, but not a true polyfill
    // Only needed for Opera Mini
  
    /* istanbul ignore next */
    function (cb) {
      return setTimeout(cb, 16);
    };
    var MutationObs = w$1.MutationObserver || w$1.WebKitMutationObserver || w$1.MozMutationObserver || null; // --- Utils ---
    // Remove a node from DOM
  
    var removeNode = function removeNode(el) {
      return el && el.parentNode && el.parentNode.removeChild(el);
    }; // 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) {
      if (!isElement(el) || !el.parentNode || !contains(d.body, el)) {
        // Note this can fail for shadow dom elements since they
        // are not a direct descendant of document.body
        return false;
      }
  
      if (el.style.display === 'none') {
        // We do this check to help with vue-test-utils when using v-show
  
        /* istanbul ignore next */
        return false;
      } // All browsers support getBoundingClientRect(), except JSDOM as it returns all 0's for values :(
      // So any tests that need isVisible will fail in JSDOM
      // Except when we override the getBCR prototype in some tests
  
  
      var bcr = getBCR(el);
      return !!(bcr && bcr.height > 0 && bcr.width > 0);
    }; // Determine if an element is disabled
  
    var isDisabled = function isDisabled(el) {
      return !isElement(el) || el.disabled || hasAttr(el, 'disabled') || hasClass(el, 'disabled');
    }; // Cause/wait-for an element to reflow its content (adjusting its height/width)
  
    var reflow = function reflow(el) {
      // Requesting an elements offsetHight will trigger a reflow of the element content
  
      /* istanbul ignore next: reflow doesn't happen in JSDOM */
      return isElement(el) && el.offsetHeight;
    }; // Select all elements matching selector. Returns `[]` if none found
  
    var selectAll = function selectAll(selector, root) {
      return from((isElement(root) ? root : d).querySelectorAll(selector));
    }; // Select a single element, returns `null` if not found
  
    var select = function select(selector, root) {
      return (isElement(root) ? root : d).querySelector(selector) || null;
    }; // Determine if an element matches a selector
  
    var matches = function matches(el, selector) {
      return isElement(el) ? matchesEl.call(el, selector) : false;
    }; // Finds closest element matching selector. Returns `null` if not found
  
    var closest = function closest(selector, root) {
      var includeRoot = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  
      if (!isElement(root)) {
        return null;
      }
  
      var el = closestEl.call(root, selector); // Native closest behaviour when `includeRoot` is truthy,
      // else emulate jQuery closest and return `null` if match is
      // the passed in root element when `includeRoot` is falsey
  
      return includeRoot ? el : el === root ? null : el;
    }; // Returns true if the parent element contains the child element
  
    var contains = function contains(parent, child) {
      return parent && isFunction(parent.contains) ? parent.contains(child) : false;
    }; // Get an element given an ID
  
    var getById = function getById(id) {
      return d.getElementById(/^#/.test(id) ? id.slice(1) : id) || null;
    }; // Add a class to an element
  
    var addClass = function addClass(el, className) {
      // We are checking for `el.classList` existence here since IE 11
      // returns `undefined` for some elements (e.g. SVG elements)
      // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2713
      if (className && isElement(el) && el.classList) {
        el.classList.add(className);
      }
    }; // Remove a class from an element
  
    var removeClass = function removeClass(el, className) {
      // We are checking for `el.classList` existence here since IE 11
      // returns `undefined` for some elements (e.g. SVG elements)
      // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2713
      if (className && isElement(el) && el.classList) {
        el.classList.remove(className);
      }
    }; // Test if an element has a class
  
    var hasClass = function hasClass(el, className) {
      // We are checking for `el.classList` existence here since IE 11
      // returns `undefined` for some elements (e.g. SVG elements)
      // See https://github.com/bootstrap-vue/bootstrap-vue/issues/2713
      if (className && isElement(el) && el.classList) {
        return el.classList.contains(className);
      }
  
      return false;
    }; // Set an attribute on an element
  
    var setAttr = function setAttr(el, attr, val) {
      if (attr && isElement(el)) {
        el.setAttribute(attr, val);
      }
    }; // 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) {
      return attr && isElement(el) ? el.getAttribute(attr) : 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) {
      return attr && isElement(el) ? el.hasAttribute(attr) : null;
    }; // Return the Bounding Client Rect of an element
    // Returns `null` if not an element
  
    /* istanbul ignore next: getBoundingClientRect() doesn't work in JSDOM */
  
    var getBCR = function getBCR(el) {
      return isElement(el) ? el.getBoundingClientRect() : null;
    }; // Get computed style object for an element
  
    /* istanbul ignore next: getComputedStyle() doesn't work in JSDOM */
  
    var getCS = function getCS(el) {
      return hasWindowSupport && isElement(el) ? w$1.getComputedStyle(el) : {};
    }; // Returns a `Selection` object representing the range of text selected
    // Returns `null` if no window support is given
  
    /* istanbul ignore next: getSelection() doesn't work in JSDOM */
  
    var getSel = function getSel() {
      return hasWindowSupport && w$1.getSelection ? w$1.getSelection() : null;
    }; // Return an element's offset with respect to document element
    // https://j11y.io/jquery/#v=git&fn=jQuery.fn.offset
  
    var offset = function offset(el)
    /* istanbul ignore next: getBoundingClientRect(), getClientRects() doesn't work in JSDOM */
    {
      var _offset = {
        top: 0,
        left: 0
      };
  
      if (!isElement(el) || el.getClientRects().length === 0) {
        return _offset;
      }
  
      var bcr = getBCR(el);
  
      if (bcr) {
        var win = el.ownerDocument.defaultView;
        _offset.top = bcr.top + win.pageYOffset;
        _offset.left = bcr.left + win.pageXOffset;
      }
  
      return _offset;
    }; // Return an element's offset with respect to to its offsetParent
    // https://j11y.io/jquery/#v=git&fn=jQuery.fn.position
  
    var position = function position(el)
    /* istanbul ignore next: getBoundingClientRect() doesn't work in JSDOM */
    {
      var _offset = {
        top: 0,
        left: 0
      };
  
      if (!isElement(el)) {
        return _offset;
      }
  
      var parentOffset = {
        top: 0,
        left: 0
      };
      var elStyles = getCS(el);
  
      if (elStyles.position === 'fixed') {
        _offset = getBCR(el) || _offset;
      } else {
        _offset = offset(el);
        var doc = el.ownerDocument;
        var 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);
          var offsetParentStyles = getCS(offsetParent);
          parentOffset.top += parseFloat(offsetParentStyles.borderTopWidth);
          parentOffset.left += parseFloat(offsetParentStyles.borderLeftWidth);
        }
      }
  
      return {
        top: _offset.top - parentOffset.top - parseFloat(elStyles.marginTop),
        left: _offset.left - parentOffset.left - parseFloat(elStyles.marginLeft)
      };
    };
  
    // Number utilities
    // Converts a value (string, number, etc) to an integer number
    // Assumes radix base 10
    // Returns NaN if the value cannot be converted
    var toInteger = function toInteger(val) {
      return parseInt(val, 10);
    }; // Converts a value (string, number, etc) to a number
    // Returns NaN if the value cannot be converted
  
    var toFloat = function toFloat(val) {
      return parseFloat(val);
    }; // Converts a value (string, number, etc) to a string
    // representation with 'precision' digits after the decimal
    // Returns the string 'NaN' if the value cannot be converted
  
    var toFixed = function toFixed(val, precision) {
      return toFloat(val).toFixed(toInteger(precision) || 0);
    };
  
    var e=function(){return (e=Object.assign||function(e){for(var t,r=1,s=arguments.length;r<s;r++)for(var a in t=arguments[r])Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e}).apply(this,arguments)},t={kebab:/-(\w)/g,styleProp:/:(.*)/,styleList:/;(?![^(]*\))/g};function r(e,t){return t?t.toUpperCase():""}function s(e){for(var s,a={},c=0,o=e.split(t.styleList);c<o.length;c++){var n=o[c].split(t.styleProp),i=n[0],l=n[1];(i=i.trim())&&("string"==typeof l&&(l=l.trim()),a[(s=i,s.replace(t.kebab,r))]=l);}return a}function a(){for(var t,r,a={},c=arguments.length;c--;)for(var o=0,n=Object.keys(arguments[c]);o<n.length;o++)switch(t=n[o]){case"class":case"style":case"directives":if(Array.isArray(a[t])||(a[t]=[]),"style"===t){var i=void 0;i=Array.isArray(arguments[c].style)?arguments[c].style:[arguments[c].style];for(var l=0;l<i.length;l++){var y=i[l];"string"==typeof y&&(i[l]=s(y));}arguments[c].style=i;}a[t]=a[t].concat(arguments[c][t]);break;case"staticClass":if(!arguments[c][t])break;void 0===a[t]&&(a[t]=""),a[t]&&(a[t]+=" "),a[t]+=arguments[c][t].trim();break;case"on":case"nativeOn":a[t]||(a[t]={});for(var p=0,f=Object.keys(arguments[c][t]||{});p<f.length;p++)r=f[p],a[t][r]?a[t][r]=[].concat(a[t][r],arguments[c][t][r]):a[t][r]=arguments[c][t][r];break;case"attrs":case"props":case"domProps":case"scopedSlots":case"staticStyle":case"hook":case"transition":a[t]||(a[t]={}),a[t]=e({},arguments[c][t],a[t]);break;case"slot":case"key":case"ref":case"tag":case"show":case"keepAlive":default:a[t]||(a[t]=arguments[c][t]);}return a}
  
    var NO_FADE_PROPS = {
      name: '',
      enterClass: '',
      enterActiveClass: '',
      enterToClass: 'show',
      leaveClass: 'show',
      leaveActiveClass: '',
      leaveToClass: ''
    };
  
    var FADE_PROPS = _objectSpread2({}, NO_FADE_PROPS, {
      enterActiveClass: 'fade',
      leaveActiveClass: 'fade'
    }); // @vue/component
  
  
    var BVTransition = /*#__PURE__*/Vue.extend({
      name: 'BVTransition',
      functional: true,
      props: {
        noFade: {
          // Only applicable to the built in transition
          // Has no effect if `trans-props` provided
          type: Boolean,
          default: false
        },
        appear: {
          // Has no effect if `trans-props` provided
          type: Boolean,
          default: false
        },
        mode: {
          // Can be overridden by user supplied trans-props
          type: String // default: undefined
  
        },
        // For user supplied transitions (if needed)
        transProps: {
          type: Object,
          default: null
        }
      },
      render: function render(h, _ref) {
        var children = _ref.children,
            data = _ref.data,
            props = _ref.props;
        var transProps = props.transProps;
  
        if (!isPlainObject(transProps)) {
          transProps = props.noFade ? NO_FADE_PROPS : FADE_PROPS;
  
          if (props.appear) {
            // Default the appear classes to equal the enter classes
            transProps = _objectSpread2({}, transProps, {
              appear: true,
              appearClass: transProps.enterClass,
              appearActiveClass: transProps.enterActiveClass,
              appearToClass: transProps.enterToClass
            });
          }
        }
  
        transProps = _objectSpread2({
          mode: props.mode
        }, transProps, {
          // We always need `css` true
          css: true
        });
        return h('transition', // Any transition event listeners will get merged here
        a(data, {
          props: transProps
        }), children);
      }
    });
  
    // In functional components, `slots` is a function so it must be called
    // first before passing to the below methods. `scopedSlots` is always an
    // object and may be undefined (for Vue < 2.6.x)
  
    /**
     * Returns true if either scoped or unscoped named slot exists
     *
     * @param {String, Array} name or name[]
     * @param {Object} scopedSlots
     * @param {Object} slots
     * @returns {Array|undefined} VNodes
     */
  
    var hasNormalizedSlot = function hasNormalizedSlot(names) {
      var $scopedSlots = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var $slots = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      // Ensure names is an array
      names = concat(names).filter(identity); // Returns true if the either a $scopedSlot or $slot exists with the specified name
  
      return names.some(function (name) {
        return $scopedSlots[name] || $slots[name];
      });
    };
    /**
     * Returns VNodes for named slot either scoped or unscoped
     *
     * @param {String, Array} name or name[]
     * @param {String} scope
     * @param {Object} scopedSlots
     * @param {Object} slots
     * @returns {Array|undefined} VNodes
     */
  
  
    var normalizeSlot = function normalizeSlot(names) {
      var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var $scopedSlots = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      var $slots = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
      // Ensure names is an array
      names = concat(names).filter(identity);
      var slot;
  
      for (var i = 0; i < names.length && !slot; i++) {
        var name = names[i];
        slot = $scopedSlots[name] || $slots[name];
      } // Note: in Vue 2.6.x, all named slots are also scoped slots
  
  
      return isFunction(slot) ? slot(scope) : slot;
    }; // Named exports
  
    var normalizeSlotMixin = {
      methods: {
        hasNormalizedSlot: function hasNormalizedSlot$1(names) {
          // Returns true if the either a $scopedSlot or $slot exists with the specified name
          // `names` can be a string name or an array of names
          return hasNormalizedSlot(names, this.$scopedSlots, this.$slots);
        },
        normalizeSlot: function normalizeSlot$1(names) {
          var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
          // Returns an array of rendered VNodes if slot found.
          // Returns undefined if not found.
          // `names` can be a string name or an array of names
          var vNodes = normalizeSlot(names, scope, this.$scopedSlots, this.$slots);
  
          return vNodes ? concat(vNodes) : vNodes;
        }
      }
    };
  
    var NAME$1 = 'BButtonClose';
    var props = {
      content: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$1, 'content');
        }
      },
      disabled: {
        type: Boolean,
        default: false
      },
      ariaLabel: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$1, 'ariaLabel');
        }
      },
      textVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$1, 'textVariant');
        }
      }
    }; // @vue/component
  
    var BButtonClose = /*#__PURE__*/Vue.extend({
      name: NAME$1,
      functional: true,
      props: props,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots;
        var $slots = slots();
        var $scopedSlots = scopedSlots || {};
        var componentData = {
          staticClass: 'close',
          class: _defineProperty({}, "text-".concat(props.textVariant), props.textVariant),
          attrs: {
            type: 'button',
            disabled: props.disabled,
            'aria-label': props.ariaLabel ? String(props.ariaLabel) : null
          },
          on: {
            click: function click(evt) {
              // Ensure click on button HTML content is also disabled
  
              /* istanbul ignore if: bug in JSDOM still emits click on inner element */
              if (props.disabled && isEvent(evt)) {
                evt.stopPropagation();
                evt.preventDefault();
              }
            }
          }
        }; // Careful not to override the default slot with innerHTML
  
        if (!hasNormalizedSlot('default', $scopedSlots, $slots)) {
          componentData.domProps = {
            innerHTML: props.content
          };
        }
  
        return h('button', a(data, componentData), normalizeSlot('default', {}, $scopedSlots, $slots));
      }
    });
  
    var NAME$2 = 'BAlert'; // Convert `show` value to a number
  
    var parseCountDown = function parseCountDown(show) {
      if (show === '' || isBoolean(show)) {
        return 0;
      }
  
      show = toInteger(show);
      return show > 0 ? show : 0;
    }; // Convert `show` value to a boolean
  
  
    var parseShow = function parseShow(show) {
      if (show === '' || show === true) {
        return true;
      }
  
      if (toInteger(show) < 1) {
        // Boolean will always return false for the above comparison
        return false;
      }
  
      return !!show;
    }; // Is a value number like (i.e. a number or a number as string)
  
  
    var isNumericLike = function isNumericLike(value) {
      return !isNaN(toInteger(value));
    }; // @vue/component
  
  
    var BAlert = /*#__PURE__*/Vue.extend({
      name: NAME$2,
      mixins: [normalizeSlotMixin],
      model: {
        prop: 'show',
        event: 'input'
      },
      props: {
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$2, 'variant');
          }
        },
        dismissible: {
          type: Boolean,
          default: false
        },
        dismissLabel: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$2, 'dismissLabel');
          }
        },
        show: {
          type: [Boolean, Number, String],
          default: false
        },
        fade: {
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          countDownTimerId: null,
          countDown: 0,
          // If initially shown, we need to set these for SSR
          localShow: parseShow(this.show)
        };
      },
      watch: {
        show: function show(newVal) {
          this.countDown = parseCountDown(newVal);
          this.localShow = parseShow(newVal);
        },
        countDown: function countDown(newVal) {
          var _this = this;
  
          this.clearTimer();
  
          if (isNumericLike(this.show)) {
            // Ignore if this.show transitions to a boolean value.
            this.$emit('dismiss-count-down', newVal);
  
            if (this.show !== newVal) {
              // Update the v-model if needed
              this.$emit('input', newVal);
            }
  
            if (newVal > 0) {
              this.localShow = true;
              this.countDownTimerId = setTimeout(function () {
                _this.countDown--;
              }, 1000);
            } else {
              // Slightly delay the hide to allow any UI updates
              this.$nextTick(function () {
                requestAF(function () {
                  _this.localShow = false;
                });
              });
            }
          }
        },
        localShow: function localShow(newVal) {
          if (!newVal && (this.dismissible || isNumericLike(this.show))) {
            // Only emit dismissed events for dismissible or auto dismissing alerts
            this.$emit('dismissed');
          }
  
          if (!isNumericLike(this.show) && this.show !== newVal) {
            // Only emit booleans if we weren't passed a number via `this.show`
            this.$emit('input', newVal);
          }
        }
      },
      created: function created() {
        this.countDown = parseCountDown(this.show);
        this.localShow = parseShow(this.show);
      },
      mounted: function mounted() {
        this.countDown = parseCountDown(this.show);
        this.localShow = parseShow(this.show);
      },
      beforeDestroy: function beforeDestroy() {
        this.clearTimer();
      },
      methods: {
        dismiss: function dismiss() {
          this.clearTimer();
          this.countDown = 0;
          this.localShow = false;
        },
        clearTimer: function clearTimer() {
          if (this.countDownTimerId) {
            clearInterval(this.countDownTimerId);
            this.countDownTimerId = null;
          }
        }
      },
      render: function render(h) {
        var $alert; // undefined
  
        if (this.localShow) {
          var $dismissBtn = h();
  
          if (this.dismissible) {
            // Add dismiss button
            $dismissBtn = h(BButtonClose, {
              attrs: {
                'aria-label': this.dismissLabel
              },
              on: {
                click: this.dismiss
              }
            }, [this.normalizeSlot('dismiss')]);
          }
  
          $alert = h('div', {
            key: this._uid,
            staticClass: 'alert',
            class: _defineProperty({
              'alert-dismissible': this.dismissible
            }, "alert-".concat(this.variant), this.variant),
            attrs: {
              role: 'alert',
              'aria-live': 'polite',
              'aria-atomic': true
            }
          }, [$dismissBtn, this.normalizeSlot('default')]);
          $alert = [$alert];
        }
  
        return h(BVTransition, {
          props: {
            noFade: !this.fade
          }
        }, $alert);
      }
    });
  
    var AlertPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BAlert: BAlert
      }
    });
  
    /**
     * Given an array of properties or an object of property keys,
     * plucks all the values off the target object, returning a new object
     * that has props that reference the original prop values
     *
     * @param {{}|string[]} keysToPluck
     * @param {{}} objToPluck
     * @param {Function} transformFn
     * @return {{}}
     */
  
    var pluckProps = 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) {
        memo[transformFn(prop)] = objToPluck[prop];
        return memo;
      }, {});
    };
  
    // String utilities
  
    var RX_TRIM_LEFT = /^\s+/;
    var RX_REGEXP_REPLACE = /[-/\\^$*+?.()|[\]{}]/g;
    var RX_UN_KEBAB = /-(\w)/g;
    var RX_HYPHENATE = /\B([A-Z])/g; // --- Utilities ---
    // Converts PascalCase or camelCase to kebab-case
  
    var kebabCase = function kebabCase(str) {
      return str.replace(RX_HYPHENATE, '-$1').toLowerCase();
    }; // Converts a kebab-case or camelCase string to PascalCase
  
    var pascalCase = function pascalCase(str) {
      str = kebabCase(str).replace(RX_UN_KEBAB, function (_, c) {
        return c ? c.toUpperCase() : '';
      });
      return str.charAt(0).toUpperCase() + str.slice(1);
    }; // Lowercases the first letter of a string and returns a new string
  
    var lowerFirst = function lowerFirst(str) {
      str = isString(str) ? str.trim() : String(str);
      return str.charAt(0).toLowerCase() + str.slice(1);
    }; // Uppercases the first letter of a string and returns a new string
  
    var upperFirst = function upperFirst(str) {
      str = isString(str) ? str.trim() : String(str);
      return str.charAt(0).toUpperCase() + str.slice(1);
    }; // Escape characters to be used in building a regular expression
  
    var escapeRegExp = function escapeRegExp(str) {
      return str.replace(RX_REGEXP_REPLACE, '\\$&');
    }; // Convert a value to a string that can be rendered
    // `undefined`/`null` will be converted to `''`
    // Plain objects and arrays will be JSON stringified
  
    var toString$1 = function toString(val) {
      var spaces = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
      return isUndefinedOrNull(val) ? '' : isArray(val) || isPlainObject(val) && val.toString === Object.prototype.toString ? JSON.stringify(val, null, spaces) : String(val);
    }; // Remove leading white space from a string
  
    var trimLeft = function trimLeft(str) {
      return toString$1(str).replace(RX_TRIM_LEFT, '');
    }; // Remove Trailing white space from a string
  
    var trim = function trim(str) {
      return toString$1(str).trim();
    }; // Lower case a string
  
    var lowerCase = function lowerCase(str) {
      return toString$1(str).toLowerCase();
    }; // Upper case a string
  
    var ANCHOR_TAG = 'a'; // Precompile RegExp
  
    var commaRE = /%2C/g;
    var encodeReserveRE = /[!'()*]/g;
    var plusRE = /\+/g;
    var queryStartRE = /^(\?|#|&)/; // Method to replace reserved chars
  
    var encodeReserveReplacer = function encodeReserveReplacer(c) {
      return '%' + c.charCodeAt(0).toString(16);
    }; // Fixed encodeURIComponent which is more conformant to RFC3986:
    // - escapes [!'()*]
    // - preserve commas
  
  
    var encode = function encode(str) {
      return encodeURIComponent(toString$1(str)).replace(encodeReserveRE, encodeReserveReplacer).replace(commaRE, ',');
    };
  
    var decode = decodeURIComponent; // Stringifies an object of query parameters
    // See: https://github.com/vuejs/vue-router/blob/dev/src/util/query.js
  
    var stringifyQueryObj = function stringifyQueryObj(obj) {
      if (!isPlainObject(obj)) {
        return '';
      }
  
      var query = keys(obj).map(function (key) {
        var val = obj[key];
  
        if (isUndefined(val)) {
          return '';
        } else if (isNull(val)) {
          return encode(key);
        } else if (isArray(val)) {
          return val.reduce(function (results, val2) {
            if (isNull(val2)) {
              results.push(encode(key));
            } else if (!isUndefined(val2)) {
              // Faster than string interpolation
              results.push(encode(key) + '=' + encode(val2));
            }
  
            return results;
          }, []).join('&');
        } // Faster than string interpolation
  
  
        return encode(key) + '=' + encode(val);
      })
      /* must check for length, as we only want to filter empty strings, not things that look falsey! */
      .filter(function (x) {
        return x.length > 0;
      }).join('&');
      return query ? "?".concat(query) : '';
    };
    var parseQuery = function parseQuery(query) {
      var parsed = {};
      query = toString$1(query).trim().replace(queryStartRE, '');
  
      if (!query) {
        return parsed;
      }
  
      query.split('&').forEach(function (param) {
        var parts = param.replace(plusRE, ' ').split('=');
        var key = decode(parts.shift());
        var val = parts.length > 0 ? decode(parts.join('=')) : null;
  
        if (isUndefined(parsed[key])) {
          parsed[key] = val;
        } else if (isArray(parsed[key])) {
          parsed[key].push(val);
        } else {
          parsed[key] = [parsed[key], val];
        }
      });
      return parsed;
    };
    var isRouterLink = function isRouterLink(tag) {
      return toString$1(tag).toLowerCase() !== ANCHOR_TAG;
    };
    var computeTag = function computeTag() {
      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
          to = _ref.to,
          disabled = _ref.disabled;
  
      var thisOrParent = arguments.length > 1 ? arguments[1] : undefined;
      return thisOrParent.$router && to && !disabled ? thisOrParent.$nuxt ? 'nuxt-link' : 'router-link' : ANCHOR_TAG;
    };
    var computeRel = function computeRel() {
      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
          target = _ref2.target,
          rel = _ref2.rel;
  
      if (target === '_blank' && isNull(rel)) {
        return 'noopener';
      }
  
      return rel || null;
    };
    var computeHref = function computeHref() {
      var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
          href = _ref3.href,
          to = _ref3.to;
  
      var tag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ANCHOR_TAG;
      var fallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '#';
      var toFallback = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '/';
  
      // We've already checked the $router in computeTag(), so isRouterLink() indicates a live router.
      // When deferring to Vue Router's router-link, don't use the href attribute at all.
      // We return null, and then remove href from the attributes passed to router-link
      if (isRouterLink(tag)) {
        return null;
      } // Return `href` when 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 (isString(to)) {
          return to || toFallback;
        } // Fallback to `to.path + to.query + to.hash` prop (if `to` is an object)
  
  
        if (isPlainObject(to) && (to.path || to.query || to.hash)) {
          var path = toString$1(to.path);
          var query = stringifyQueryObj(to.query);
          var hash = toString$1(to.hash);
          hash = !hash || hash.charAt(0) === '#' ? hash : "#".concat(hash);
          return "".concat(path).concat(query).concat(hash) || toFallback;
        }
      } // If nothing is provided return the fallback
  
  
      return fallback;
    };
  
    /**
     * 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 {{}}
     */
  
    var propsFactory = function propsFactory() {
      return {
        href: {
          type: String,
          default: null
        },
        rel: {
          type: String,
          default: null
        },
        target: {
          type: String,
          default: '_self'
        },
        active: {
          type: Boolean,
          default: false
        },
        disabled: {
          type: Boolean,
          default: false
        },
        // router-link specific props
        to: {
          type: [String, Object],
          default: null
        },
        append: {
          type: Boolean,
          default: false
        },
        replace: {
          type: Boolean,
          default: false
        },
        event: {
          type: [String, Array],
          default: 'click'
        },
        activeClass: {
          type: String // default: undefined
  
        },
        exact: {
          type: Boolean,
          default: false
        },
        exactActiveClass: {
          type: String // default: undefined
  
        },
        routerTag: {
          type: String,
          default: 'a'
        },
        // nuxt-link specific prop(s)
        noPrefetch: {
          type: Boolean,
          default: false
        }
      };
    };
  
    var BLink = /*#__PURE__*/Vue.extend({
      name: 'BLink',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      props: propsFactory(),
      computed: {
        computedTag: function computedTag() {
          // We don't pass `this` as the first arg as we need reactivity of the props
          return computeTag({
            to: this.to,
            disabled: this.disabled
          }, this);
        },
        isRouterLink: function isRouterLink$1() {
          return isRouterLink(this.computedTag);
        },
        computedRel: function computedRel() {
          // We don't pass `this` as the first arg as we need reactivity of the props
          return computeRel({
            target: this.target,
            rel: this.rel
          });
        },
        computedHref: function computedHref() {
          // We don't pass `this` as the first arg as we need reactivity of the props
          return computeHref({
            to: this.to,
            href: this.href
          }, this.computedTag);
        },
        computedProps: function computedProps() {
          return this.isRouterLink ? _objectSpread2({}, this.$props, {
            tag: this.routerTag
          }) : {};
        }
      },
      methods: {
        onClick: function onClick(evt) {
          var _arguments = arguments;
          var evtIsEvent = isEvent(evt);
          var isRouterLink = this.isRouterLink;
          var suppliedHandler = this.$listeners.click;
  
          if (evtIsEvent && this.disabled) {
            // Stop event from bubbling up
            evt.stopPropagation(); // Kill the event loop attached to this specific `EventTarget`
            // Needed to prevent `vue-router` for doing its thing
  
            evt.stopImmediatePropagation();
          } else {
            /* istanbul ignore next: difficult to test, but we know it works */
            if (isRouterLink && evt.currentTarget.__vue__) {
              // Router links do not emit instance `click` events, so we
              // add in an `$emit('click', evt)` on its Vue instance
              evt.currentTarget.__vue__.$emit('click', evt);
            } // Call the suppliedHandler(s), if any provided
  
  
            concat(suppliedHandler).filter(function (h) {
              return isFunction(h);
            }).forEach(function (handler) {
              handler.apply(void 0, _toConsumableArray(_arguments));
            }); // Emit the global `$root` click event
  
            this.$root.$emit('clicked::link', evt);
          } // Stop scroll-to-top behavior or navigation on
          // regular links when href is just '#'
  
  
          if (evtIsEvent && (this.disabled || !isRouterLink && this.computedHref === '#')) {
            evt.preventDefault();
          }
        },
        focus: function focus() {
          if (this.$el && this.$el.focus) {
            this.$el.focus();
          }
        },
        blur: function blur() {
          if (this.$el && this.$el.blur) {
            this.$el.blur();
          }
        }
      },
      render: function render(h) {
        var tag = this.computedTag;
        var rel = this.computedRel;
        var href = this.computedHref;
        var isRouterLink = this.isRouterLink;
        var componentData = {
          class: {
            active: this.active,
            disabled: this.disabled
          },
          attrs: _objectSpread2({}, this.$attrs, {
            rel: rel,
            target: this.target,
            tabindex: this.disabled ? '-1' : isUndefined(this.$attrs.tabindex) ? null : this.$attrs.tabindex,
            'aria-disabled': this.disabled ? 'true' : null
          }),
          props: this.computedProps
        }; // Add the event handlers. We must use `nativeOn` for
        // `<router-link>`/`<nuxt-link>` instead of `on`
  
        componentData[isRouterLink ? 'nativeOn' : 'on'] = _objectSpread2({}, this.$listeners, {
          // We want to overwrite any click handler since our callback
          // will invoke the user supplied handler(s) if `!this.disabled`
          click: this.onClick
        }); // If href attribute exists on <router-link> (even undefined or null) it fails working on
        // SSR, so we explicitly add it here if needed (i.e. if computedHref() is truthy)
  
        if (href) {
          componentData.attrs.href = href;
        } else {
          // Ensure the prop HREF does not exist for router links
          delete componentData.props.href;
        }
  
        return h(tag, componentData, this.normalizeSlot('default'));
      }
    });
  
    var NAME$3 = 'BBadge';
    var linkProps = propsFactory();
    delete linkProps.href.default;
    delete linkProps.to.default;
    var props$1 = _objectSpread2({}, linkProps, {
      tag: {
        type: String,
        default: 'span'
      },
      variant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$3, 'variant');
        }
      },
      pill: {
        type: Boolean,
        default: false
      }
    }); // @vue/component
  
    var BBadge = /*#__PURE__*/Vue.extend({
      name: NAME$3,
      functional: true,
      props: props$1,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var isBLink = props.href || props.to;
        var tag = isBLink ? BLink : props.tag;
        var componentData = {
          staticClass: 'badge',
          class: [props.variant ? "badge-".concat(props.variant) : 'badge-secondary', {
            'badge-pill': props.pill,
            active: props.active,
            disabled: props.disabled
          }],
          props: isBLink ? pluckProps(linkProps, props) : {}
        };
        return h(tag, a(data, componentData), children);
      }
    });
  
    var BadgePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BBadge: BBadge
      }
    });
  
    var stripTagsRegex = /(<([^>]+)>)/gi; // Removes any thing that looks like an HTML tag from the supplied string
  
    var stripTags = function stripTags() {
      var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
      return String(text).replace(stripTagsRegex, '');
    }; // Generate a domProps object for either innerHTML, textContent or nothing
  
    var htmlOrText = function htmlOrText(innerHTML, textContent) {
      return innerHTML ? {
        innerHTML: innerHTML
      } : textContent ? {
        textContent: textContent
      } : {};
    };
  
    var props$2 = _objectSpread2({}, propsFactory(), {
      text: {
        type: String,
        default: null
      },
      html: {
        type: String,
        default: null
      },
      ariaCurrent: {
        type: String,
        default: 'location'
      }
    }); // @vue/component
  
    var BBreadcrumbLink = /*#__PURE__*/Vue.extend({
      name: 'BBreadcrumbLink',
      functional: true,
      props: props$2,
      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$2, suppliedProps)
        };
  
        if (suppliedProps.active) {
          componentData.attrs = {
            'aria-current': suppliedProps.ariaCurrent
          };
        }
  
        if (!children) {
          componentData.domProps = htmlOrText(suppliedProps.html, suppliedProps.text);
        }
  
        return h(tag, a(data, componentData), children);
      }
    });
  
    var BBreadcrumbItem = /*#__PURE__*/Vue.extend({
      name: 'BBreadcrumbItem',
      functional: true,
      props: props$2,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h('li', a(data, {
          staticClass: 'breadcrumb-item',
          class: {
            active: props.active
          }
        }), [h(BBreadcrumbLink, {
          props: props
        }, children)]);
      }
    });
  
    var props$3 = {
      items: {
        type: Array,
        default: null
      }
    }; // @vue/component
  
    var BBreadcrumb = /*#__PURE__*/Vue.extend({
      name: 'BBreadcrumb',
      functional: true,
      props: props$3,
      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 (!isObject(item)) {
              item = {
                text: toString$1(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(BBreadcrumbItem, {
              props: _objectSpread2({}, item, {
                active: active
              })
            });
          });
        }
  
        return h('ol', a(data, {
          staticClass: 'breadcrumb'
        }), childNodes);
      }
    });
  
    var BreadcrumbPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BBreadcrumb: BBreadcrumb,
        BBreadcrumbItem: BBreadcrumbItem,
        BBreadcrumbLink: BBreadcrumbLink
      }
    });
  
    /*
     * Key Codes (events)
     */
    var KEY_CODES = freeze({
      SPACE: 32,
      ENTER: 13,
      ESC: 27,
      LEFT: 37,
      UP: 38,
      RIGHT: 39,
      DOWN: 40,
      PAGEUP: 33,
      PAGEDOWN: 34,
      HOME: 36,
      END: 35,
      TAB: 9,
      SHIFT: 16,
      CTRL: 17,
      BACKSPACE: 8,
      ALT: 18,
      PAUSE: 19,
      BREAK: 19,
      INSERT: 45,
      INS: 45,
      DELETE: 46
    });
  
    var NAME$4 = 'BButton';
    var btnProps = {
      block: {
        type: Boolean,
        default: false
      },
      disabled: {
        type: Boolean,
        default: false
      },
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$4, 'size');
        }
      },
      variant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$4, 'variant');
        }
      },
      type: {
        type: String,
        default: 'button'
      },
      tag: {
        type: String,
        default: 'button'
      },
      pill: {
        type: Boolean,
        default: false
      },
      squared: {
        type: Boolean,
        default: false
      },
      pressed: {
        // Tri-state: `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$4 = _objectSpread2({}, linkProps$1, {}, btnProps); // --- Helper methods ---
    // Returns `true` if a tag's name equals `name`
  
    var tagIs = function tagIs(tag, name) {
      return toString$1(tag).toLowerCase() === toString$1(name).toLowerCase();
    }; // Focus handler for toggle buttons
    // Needs class of 'focus' when focused
  
  
    var handleFocus = function handleFocus(evt) {
      if (evt.type === 'focusin') {
        addClass(evt.target, 'focus');
      } else if (evt.type === 'focusout') {
        removeClass(evt.target, 'focus');
      }
    }; // Is the requested button a link?
    // If tag prop is set to `a`, we use a <b-link> to get proper disabled handling
  
  
    var isLink = function isLink(props) {
      return props.href || props.to || tagIs(props.tag, 'a');
    }; // Is the button to be a toggle button?
  
  
    var isToggle = function isToggle(props) {
      return isBoolean(props.pressed);
    }; // Is the button "really" a button?
  
  
    var isButton = function isButton(props) {
      return !(isLink(props) || props.tag && !tagIs(props.tag, 'button'));
    }; // Is the requested tag not a button or link?
  
  
    var isNonStandardTag = function isNonStandardTag(props) {
      return !isLink(props) && !isButton(props);
    }; // Compute required classes (non static classes)
  
  
    var computeClass = function computeClass(props) {
      var _ref;
  
      return ["btn-".concat(props.variant || getComponentConfig(NAME$4, 'variant')), (_ref = {}, _defineProperty(_ref, "btn-".concat(props.size), props.size), _defineProperty(_ref, 'btn-block', props.block), _defineProperty(_ref, 'rounded-pill', props.pill), _defineProperty(_ref, 'rounded-0', props.squared && !props.pill), _defineProperty(_ref, "disabled", props.disabled), _defineProperty(_ref, "active", props.pressed), _ref)];
    }; // Compute the link props to pass to b-link (if required)
  
  
    var computeLinkProps = function computeLinkProps(props) {
      return isLink(props) ? pluckProps(linkPropKeys, props) : null;
    }; // Compute the attributes for a button
  
  
    var computeAttrs = function computeAttrs(props, data) {
      var button = isButton(props);
      var link = isLink(props);
      var toggle = isToggle(props);
      var nonStandardTag = isNonStandardTag(props);
      var hashLink = link && props.href === '#';
      var role = data.attrs && data.attrs.role ? data.attrs.role : null;
      var tabindex = data.attrs ? data.attrs.tabindex : null;
  
      if (nonStandardTag || hashLink) {
        tabindex = '0';
      }
  
      return {
        // Type only used for "real" buttons
        type: button && !link ? props.type : null,
        // Disabled only set on "real" buttons
        disabled: button ? props.disabled : null,
        // We add a role of button when the tag is not a link or button for ARIA
        // Don't bork any role provided in `data.attrs` when `isLink` or `isButton`
        // Except when link has `href` of `#`
        role: nonStandardTag || hashLink ? 'button' : role,
        // We set the `aria-disabled` state for non-standard tags
        'aria-disabled': nonStandardTag ? String(props.disabled) : null,
        // For toggles, we need to set the pressed state for ARIA
        'aria-pressed': toggle ? String(props.pressed) : null,
        // `autocomplete="off"` is needed in toggle mode to prevent some browsers
        // from remembering the previous setting when using the back button
        autocomplete: toggle ? 'off' : null,
        // `tabindex` is used when the component is not a button
        // Links are tabbable, but don't allow disabled, while non buttons or links
        // are not tabbable, so we mimic that functionality by disabling tabbing
        // when disabled, and adding a `tabindex="0"` to non buttons or non links
        tabindex: props.disabled && !button ? '-1' : tabindex
      };
    }; // @vue/component
  
  
    var BButton = /*#__PURE__*/Vue.extend({
      name: NAME$4,
      functional: true,
      props: props$4,
      render: function render(h, _ref2) {
        var props = _ref2.props,
            data = _ref2.data,
            listeners = _ref2.listeners,
            children = _ref2.children;
        var toggle = isToggle(props);
        var link = isLink(props);
        var nonStandardTag = isNonStandardTag(props);
        var hashLink = link && props.href === '#';
        var on = {
          keydown: function keydown(evt) {
            // When the link is a `href="#"` or a non-standard tag (has `role="button"`),
            // we add a keydown handlers for SPACE/ENTER
  
            /* istanbul ignore next */
            if (props.disabled || !(nonStandardTag || hashLink)) {
              return;
            }
  
            var keyCode = evt.keyCode; // Add SPACE handler for `href="#"` and ENTER handler for non-standard tags
  
            if (keyCode === KEY_CODES.SPACE || keyCode === KEY_CODES.ENTER && nonStandardTag) {
              var target = evt.currentTarget || evt.target;
              evt.preventDefault();
              target.click();
            }
          },
          click: function click(evt) {
            /* istanbul ignore if: blink/button disabled should handle this */
            if (props.disabled && isEvent(evt)) {
              evt.stopPropagation();
              evt.preventDefault();
            } else if (toggle && listeners && listeners['update:pressed']) {
              // Send `.sync` updates to any "pressed" prop (if `.sync` listeners)
              // `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 (isFunction(fn)) {
                  fn(!props.pressed);
                }
              });
            }
          }
        };
  
        if (toggle) {
          on.focusin = handleFocus;
          on.focusout = handleFocus;
        }
  
        var componentData = {
          staticClass: 'btn',
          class: computeClass(props),
          props: computeLinkProps(props),
          attrs: computeAttrs(props, data),
          on: on
        };
        return h(link ? BLink : props.tag, a(data, componentData), children);
      }
    });
  
    var ButtonPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BButton: BButton,
        BBtn: BButton,
        BButtonClose: BButtonClose,
        BBtnClose: BButtonClose
      }
    });
  
    var NAME$5 = 'BButtonGroup';
    var props$5 = {
      vertical: {
        type: Boolean,
        default: false
      },
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig('BButton', 'size');
        }
      },
      tag: {
        type: String,
        default: 'div'
      },
      ariaRole: {
        type: String,
        default: 'group'
      }
    }; // @vue/component
  
    var BButtonGroup = /*#__PURE__*/Vue.extend({
      name: NAME$5,
      functional: true,
      props: props$5,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          class: _defineProperty({
            'btn-group': !props.vertical,
            'btn-group-vertical': props.vertical
          }, "btn-group-".concat(props.size), props.size),
          attrs: {
            role: props.ariaRole
          }
        }), children);
      }
    });
  
    var ButtonGroupPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BButtonGroup: BButtonGroup,
        BBtnGroup: BButtonGroup
      }
    });
  
    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(','); // @vue/component
  
    var BButtonToolbar = /*#__PURE__*/Vue.extend({
      name: 'BButtonToolbar',
      mixins: [normalizeSlotMixin],
      props: {
        justify: {
          type: Boolean,
          default: false
        },
        keyNav: {
          type: Boolean,
          default: false
        }
      },
      mounted: function mounted() {
        if (this.keyNav) {
          // Pre-set the tabindexes if the markup does not include tabindex="-1" on the toolbar items
          this.getItems();
        }
      },
      methods: {
        onFocusin: function onFocusin(evt) {
          if (evt.target === this.$el) {
            evt.preventDefault();
            evt.stopPropagation();
            this.focusFirst(evt);
          }
        },
        stop: function stop(evt) {
          evt.preventDefault();
          evt.stopPropagation();
        },
        onKeydown: function onKeydown(evt) {
          if (!this.keyNav) {
            /* istanbul ignore next: should never happen */
            return;
          }
  
          var key = evt.keyCode;
          var shift = evt.shiftKey;
  
          if (key === KEY_CODES.UP || key === KEY_CODES.LEFT) {
            this.stop(evt);
            shift ? this.focusFirst(evt) : this.focusPrev(evt);
          } else if (key === KEY_CODES.DOWN || key === KEY_CODES.RIGHT) {
            this.stop(evt);
            shift ? this.focusLast(evt) : this.focusNext(evt);
          }
        },
        setItemFocus: function setItemFocus(item) {
          item && item.focus && item.focus();
        },
        focusFirst: function focusFirst() {
          var items = this.getItems();
          this.setItemFocus(items[0]);
        },
        focusPrev: function focusPrev(evt) {
          var items = this.getItems();
          var index = items.indexOf(evt.target);
  
          if (index > -1) {
            items = items.slice(0, index).reverse();
            this.setItemFocus(items[0]);
          }
        },
        focusNext: function focusNext(evt) {
          var items = this.getItems();
          var index = items.indexOf(evt.target);
  
          if (index > -1) {
            items = items.slice(index + 1);
            this.setItemFocus(items[0]);
          }
        },
        focusLast: function focusLast() {
          var items = this.getItems().reverse();
          this.setItemFocus(items[0]);
        },
        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);
          });
        }
      },
      render: function render(h) {
        return h('div', {
          staticClass: 'btn-toolbar',
          class: {
            'justify-content-between': this.justify
          },
          attrs: {
            role: 'toolbar',
            tabindex: this.keyNav ? '0' : null
          },
          on: this.keyNav ? {
            focusin: this.onFocusin,
            keydown: this.onKeydown
          } : {}
        }, [this.normalizeSlot('default')]);
      }
    });
  
    var ButtonToolbarPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BButtonToolbar: BButtonToolbar,
        BBtnToolbar: BButtonToolbar
      }
    });
  
    // Handles when arrays are "sparse" (array.every(...) doesn't handle sparse)
  
    var compareArrays = function compareArrays(a, b) {
      if (a.length !== b.length) {
        return false;
      }
  
      var equal = true;
  
      for (var i = 0; equal && i < a.length; i++) {
        equal = looseEqual(a[i], b[i]);
      }
  
      return equal;
    };
    /**
     * 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
     */
  
  
    var looseEqual = function looseEqual(a, b) {
      if (a === b) {
        return true;
      }
  
      var aValidType = isDate(a);
      var bValidType = isDate(b);
  
      if (aValidType || bValidType) {
        return aValidType && bValidType ? a.getTime() === b.getTime() : false;
      }
  
      aValidType = isArray(a);
      bValidType = isArray(b);
  
      if (aValidType || bValidType) {
        return aValidType && bValidType ? compareArrays(a, b) : false;
      }
  
      aValidType = isObject(a);
      bValidType = isObject(b);
  
      if (aValidType || bValidType) {
        /* istanbul ignore if: this if will probably never be called */
        if (!aValidType || !bValidType) {
          return false;
        }
  
        var aKeysCount = keys(a).length;
        var bKeysCount = keys(b).length;
  
        if (aKeysCount !== bKeysCount) {
          return false;
        }
  
        for (var key in a) {
          // eslint-disable-next-line no-prototype-builtins
          var aHasKey = a.hasOwnProperty(key); // eslint-disable-next-line no-prototype-builtins
  
          var bHasKey = b.hasOwnProperty(key);
  
          if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) {
            return false;
          }
        }
      }
  
      return String(a) === String(b);
    };
  
    var RX_DATE = /^\d+-\d+-\d+$/; // --- Date utility methods ---
    // Create or clone a date (`new Date(...)` shortcut)
  
    var createDate = function createDate() {
      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
  
      return _construct(Date, args);
    }; // Parse a date sting, or Date object, into a Date object (with no time information)
  
    var parseYMD = function parseYMD(date) {
      if (isString(date) && RX_DATE.test(date.trim())) {
        var _date$split$map = date.split('-').map(toInteger),
            _date$split$map2 = _slicedToArray(_date$split$map, 3),
            year = _date$split$map2[0],
            month = _date$split$map2[1],
            day = _date$split$map2[2];
  
        return createDate(year, month - 1, day);
      } else if (isDate(date)) {
        return createDate(date.getFullYear(), date.getMonth(), date.getDate());
      }
  
      return null;
    }; // Format a date object as `YYYY-MM-DD` format
  
    var formatYMD = function formatYMD(date) {
      date = parseYMD(date);
  
      if (!date) {
        return null;
      }
  
      var year = date.getFullYear();
      var month = "0".concat(date.getMonth() + 1).slice(-2);
      var day = "0".concat(date.getDate()).slice(-2);
      return "".concat(year, "-").concat(month, "-").concat(day);
    }; // Given a locale (or locales), resolve the browser available locale
  
    var resolveLocale = function resolveLocale(locales)
    /* istanbul ignore next */
    {
      var calendar = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'gregory';
      locales = concat(locales).filter(identity);
      var fmt = new Intl.DateTimeFormat(locales, {
        calendar: calendar
      });
      return fmt.resolvedOptions().locale;
    }; // Create a `Intl.DateTimeFormat` formatter function
  
    var createDateFormatter = function createDateFormatter(locale, options)
    /* istanbul ignore next */
    {
      var dtf = new Intl.DateTimeFormat(locale, options);
      return dtf.format;
    }; // Determine if two dates are the same date (ignoring time portion)
  
    var datesEqual = function datesEqual(date1, date2) {
      // Returns true of the date portion of two date objects are equal
      // We don't compare the time portion
      return formatYMD(date1) === formatYMD(date2);
    }; // --- Date "math" utility methods (for BCalendar component mainly) ---
  
    var firstDateOfMonth = function firstDateOfMonth(date) {
      date = createDate(date);
      date.setDate(1);
      return date;
    };
    var lastDateOfMonth = function lastDateOfMonth(date) {
      date = createDate(date);
      date.setMonth(date.getMonth() + 1);
      date.setDate(0);
      return date;
    };
    var oneMonthAgo = function oneMonthAgo(date) {
      date = createDate(date);
      var month = date.getMonth();
      date.setMonth(month - 1);
  
      if (date.getMonth() === month) {
        date.setDate(0);
      }
  
      return date;
    };
    var oneMonthAhead = function oneMonthAhead(date) {
      date = createDate(date);
      var month = date.getMonth();
      date.setMonth(month + 1);
  
      if (date.getMonth() === (month + 2) % 12) {
        date.setDate(0);
      }
  
      return date;
    };
    var oneYearAgo = function oneYearAgo(date) {
      date = createDate(date);
      var month = date.getMonth();
      date.setMonth(month - 12);
  
      if (date.getMonth() !== month) {
        date.setDate(0);
      }
  
      return date;
    };
    var oneYearAhead = function oneYearAhead(date) {
      date = createDate(date);
      var month = date.getMonth();
      date.setMonth(month + 12);
  
      if (date.getMonth() !== month) {
        date.setDate(0);
      }
  
      return date;
    };
  
    // Localization utilities
  
    var RTL_LANGS = ['ar', 'az', 'ckb', 'fa', 'he', 'ks', 'lrc', 'mzn', 'ps', 'sd', 'te', 'ug', 'ur', 'yi'].map(function (locale) {
      return locale.toLowerCase();
    }); // Precompile RegExpr
  
    var RX_STRIP_MODS = /-u-.+/; // Returns true if the locale is RTL
  
    var isLocaleRTL = function isLocaleRTL(locale) {
      // Determines if the locale is RTL (only single locale supported)
      var parts = toString$1(locale).toLowerCase().replace(RX_STRIP_MODS, '').split('-');
      var locale1 = parts.slice(0, 2).join('-');
      var locale2 = parts[0];
      return arrayIncludes(RTL_LANGS, locale1) || arrayIncludes(RTL_LANGS, locale2);
    };
  
    /*
     * SSR Safe Client Side ID attribute generation
     * id's can only be generated client side, after mount.
     * this._uid is not synched between server and client.
     */
    // @vue/component
    var idMixin = {
      props: {
        id: {
          type: String,
          default: null
        }
      },
      data: function data() {
        return {
          localId_: null
        };
      },
      computed: {
        safeId: function safeId() {
          // Computed property that returns a dynamic function for creating the ID.
          // Reacts to changes in both .id and .localId_ And regens a new function
          var id = this.id || this.localId_; // We return a function that accepts an optional suffix string
          // So this computed prop looks and works like a method!!!
          // But benefits from Vue's Computed prop caching
  
          var fn = function fn(suffix) {
            if (!id) {
              return null;
            }
  
            suffix = String(suffix || '').replace(/\s+/g, '_');
            return suffix ? id + '_' + suffix : id;
          };
  
          return fn;
        }
      },
      mounted: function mounted() {
        var _this = this;
  
        // mounted only occurs client side
        this.$nextTick(function () {
          // Update dom with auto ID after dom loaded to prevent
          // SSR hydration errors.
          _this.localId_ = "__BVID__".concat(_this._uid);
        });
      }
    };
  
    var commonIconProps = {
      variant: {
        type: String,
        default: null
      },
      fontScale: {
        type: [Number, String],
        default: 1
      },
      scale: {
        type: [Number, String],
        default: 1
      },
      rotate: {
        type: [Number, String],
        default: 0
      },
      flipH: {
        type: Boolean,
        default: false
      },
      flipV: {
        type: Boolean,
        default: false
      },
      shiftH: {
        type: [Number, String],
        default: 0
      },
      shiftV: {
        type: [Number, String],
        default: 0
      }
    }; // Base attributes needed on all icons
  
    var baseAttrs = {
      width: '1em',
      height: '1em',
      viewBox: '0 0 20 20',
      focusable: 'false',
      role: 'img',
      alt: 'icon'
    }; // Shared private base component to reduce bundle/runtime size
    // @vue/component
  
    var BVIconBase = /*#__PURE__*/Vue.extend({
      name: 'BVIconBase',
      functional: true,
      props: _objectSpread2({
        content: {
          type: String
        },
        stacked: {
          type: Boolean,
          default: false
        }
      }, commonIconProps),
      render: function render(h, _ref) {
        var data = _ref.data,
            props = _ref.props,
            children = _ref.children;
        var fontScale = Math.max(toFloat(props.fontScale) || 1, 0) || 1;
        var scale = Math.max(toFloat(props.scale) || 1, 0) || 1;
        var rotate = toFloat(props.rotate) || 0;
        var shiftH = toFloat(props.shiftH) || 0;
        var shiftV = toFloat(props.shiftV) || 0;
        var flipH = props.flipH;
        var flipV = props.flipV; // Compute the transforms
        // Note that order is important as SVG transforms are applied in order from
        // left to right and we want flipping/scale to occur before rotation
        // Note shifting is applied separately
        // Assumes that the viewbox is `0 0 20 20` (`10 10` is the center)
  
        var hasScale = flipH || flipV || scale !== 1;
        var hasTransforms = hasScale || rotate;
        var hasShift = shiftH || shiftV;
        var transforms = [hasTransforms ? 'translate(10 10)' : null, hasScale ? "scale(".concat((flipH ? -1 : 1) * scale, " ").concat((flipV ? -1 : 1) * scale, ")") : null, rotate ? "rotate(".concat(rotate, ")") : null, hasTransforms ? 'translate(-10 -10)' : null].filter(identity); // Handling stacked icons
  
        var isStacked = props.stacked;
        var hasContent = !isUndefinedOrNull(props.content); // We wrap the content in a `<g>` for handling the transforms (except shift)
  
        var $inner = h('g', {
          attrs: {
            transform: transforms.join(' ') || null
          },
          domProps: hasContent ? {
            innerHTML: props.content || ''
          } : {}
        }, children); // If needed, we wrap in an additional `<g>` in order to handle the shifting
  
        if (hasShift) {
          $inner = h('g', {
            attrs: {
              transform: "translate(".concat(20 * shiftH / 16, " ").concat(-20 * shiftV / 16, ")")
            }
          }, [$inner]);
        }
  
        return h('svg', a({
          staticClass: 'b-icon bi',
          class: _defineProperty({}, "text-".concat(props.variant), !!props.variant),
          attrs: baseAttrs,
          style: isStacked ? {} : {
            fontSize: fontScale === 1 ? null : "".concat(fontScale * 100, "%")
          }
        }, // Merge in user supplied data
        data, // If icon is stacked, null out some attrs
        isStacked ? {
          attrs: {
            width: null,
            height: null,
            role: null,
            alt: null
          }
        } : {}, // These cannot be overridden by users
        {
          attrs: {
            xmlns: isStacked ? null : 'http://www.w3.org/2000/svg',
            fill: 'currentColor'
          }
        }), [$inner]);
      }
    });
  
    /**
     * Icon component generator function
     *
     * @param {string} icon name (minus the leading `BIcon`)
     * @param {string} raw `innerHTML` for SVG
     * @return {VueComponent}
     */
  
    var makeIcon = function makeIcon(name, content) {
      // For performance reason we pre-compute some values, so that
      // they are not computed on each render of the icon component
      var iconName = "BIcon".concat(pascalCase(name));
      var iconNameClass = "bi-".concat(kebabCase(name));
      var svgContent = trim(content || ''); // Return the icon component definition
  
      return (/*#__PURE__*/Vue.extend({
          name: iconName,
          functional: true,
          props: _objectSpread2({}, commonIconProps, {
            stacked: {
              type: Boolean,
              default: false
            }
          }),
          render: function render(h, _ref) {
            var data = _ref.data,
                props = _ref.props;
            return h(BVIconBase, a(data, {
              staticClass: iconNameClass,
              props: _objectSpread2({}, props, {
                content: svgContent
              })
            }));
          }
        })
      );
    };
  
    // --- BEGIN AUTO-GENERATED FILE ---
  
    var BIconBlank = /*#__PURE__*/makeIcon('Blank', ''); // --- Bootstrap Icons ---
    var BIconCalendar = /*#__PURE__*/makeIcon('Calendar', '<path fill-rule="evenodd" d="M16 2H4a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V4a2 2 0 00-2-2zM3 5.857C3 5.384 3.448 5 4 5h12c.552 0 1 .384 1 .857v10.286c0 .473-.448.857-1 .857H4c-.552 0-1-.384-1-.857V5.857z" clip-rule="evenodd"/><path fill-rule="evenodd" d="M8.5 9a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2zm-9 3a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2zm-9 3a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2zm3 0a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/>');
    var BIconCalendarFill = /*#__PURE__*/makeIcon('CalendarFill', '<path d="M2 4a2 2 0 012-2h12a2 2 0 012 2H2z"/><path fill-rule="evenodd" d="M2 5h16v11a2 2 0 01-2 2H4a2 2 0 01-2-2V5zm6.5 4a1 1 0 100-2 1 1 0 000 2zm4-1a1 1 0 11-2 0 1 1 0 012 0zm2 1a1 1 0 100-2 1 1 0 000 2zm-8 2a1 1 0 11-2 0 1 1 0 012 0zm2 1a1 1 0 100-2 1 1 0 000 2zm4-1a1 1 0 11-2 0 1 1 0 012 0zm2 1a1 1 0 100-2 1 1 0 000 2zm-8 2a1 1 0 11-2 0 1 1 0 012 0zm2 1a1 1 0 100-2 1 1 0 000 2zm4-1a1 1 0 11-2 0 1 1 0 012 0z" clip-rule="evenodd"/>');
    var BIconChevronDown = /*#__PURE__*/makeIcon('ChevronDown', '<path fill-rule="evenodd" d="M3.646 6.646a.5.5 0 01.708 0L10 12.293l5.646-5.647a.5.5 0 01.708.708l-6 6a.5.5 0 01-.708 0l-6-6a.5.5 0 010-.708z" clip-rule="evenodd"/>');
    var BIconChevronLeft = /*#__PURE__*/makeIcon('ChevronLeft', '<path fill-rule="evenodd" d="M13.354 3.646a.5.5 0 010 .708L7.707 10l5.647 5.646a.5.5 0 01-.708.708l-6-6a.5.5 0 010-.708l6-6a.5.5 0 01.708 0z" clip-rule="evenodd"/>');
    var BIconCircleFill = /*#__PURE__*/makeIcon('CircleFill', '<circle cx="10" cy="10" r="8"/>');
    var BIconClock = /*#__PURE__*/makeIcon('Clock', '<path fill-rule="evenodd" d="M10 17a7 7 0 100-14 7 7 0 000 14zm8-7a8 8 0 11-16 0 8 8 0 0116 0z" clip-rule="evenodd"/><path fill-rule="evenodd" d="M10 4a.5.5 0 01.5.5V10a.5.5 0 01-.5.5H5.5a.5.5 0 010-1h4v-5A.5.5 0 0110 4z" clip-rule="evenodd"/>');
    var BIconClockFill = /*#__PURE__*/makeIcon('ClockFill', '<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM5.5 9.5h4v-5a.5.5 0 011 0V10a.5.5 0 01-.5.5H5.5a.5.5 0 010-1z" clip-rule="evenodd"/>');
    var BIconDash = /*#__PURE__*/makeIcon('Dash', '<path fill-rule="evenodd" d="M5.5 10a.5.5 0 01.5-.5h8a.5.5 0 010 1H6a.5.5 0 01-.5-.5z" clip-rule="evenodd"/>');
    var BIconPlus = /*#__PURE__*/makeIcon('Plus', '<path fill-rule="evenodd" d="M10 5.5a.5.5 0 01.5.5v4a.5.5 0 01-.5.5H6a.5.5 0 010-1h3.5V6a.5.5 0 01.5-.5z" clip-rule="evenodd"/><path fill-rule="evenodd" d="M9.5 10a.5.5 0 01.5-.5h4a.5.5 0 010 1h-3.5V14a.5.5 0 01-1 0v-4z" clip-rule="evenodd"/>');
     // --- END AUTO-GENERATED FILE ---
  
    var BIconstack = /*#__PURE__*/Vue.extend({
      name: 'BIconstack',
      functional: true,
      props: _objectSpread2({}, commonIconProps),
      render: function render(h, _ref) {
        var data = _ref.data,
            props = _ref.props,
            children = _ref.children;
        return h(BVIconBase, a(data, {
          staticClass: 'b-iconstack',
          props: _objectSpread2({}, props, {
            stacked: false
          })
        }), children);
      }
    });
  
    var NAME$6 = 'BCalendar'; // Key Codes
  
    var UP = KEY_CODES.UP,
        DOWN = KEY_CODES.DOWN,
        LEFT = KEY_CODES.LEFT,
        RIGHT = KEY_CODES.RIGHT,
        PAGEUP = KEY_CODES.PAGEUP,
        PAGEDOWN = KEY_CODES.PAGEDOWN,
        HOME = KEY_CODES.HOME,
        END = KEY_CODES.END,
        ENTER = KEY_CODES.ENTER,
        SPACE = KEY_CODES.SPACE; // --- BCalendar component ---
    // @vue/component
  
    var BCalendar = Vue.extend({
      name: NAME$6,
      mixins: [idMixin, normalizeSlotMixin],
      model: {
        // Even though this is the default that Vue assumes, we need
        // to add it for the docs to reflect that this is the model
        // And also for some validation libraries to work
        prop: 'value',
        event: 'input'
      },
      props: {
        value: {
          type: [String, Date] // default: null
  
        },
        valueAsDate: {
          // Always return the `v-model` value as a date object
          type: Boolean,
          default: false
        },
        disabled: {
          type: Boolean,
          default: false
        },
        readonly: {
          type: Boolean,
          default: false
        },
        min: {
          type: [String, Date] // default: null
  
        },
        max: {
          type: [String, Date] // default: null
  
        },
        dateDisabledFn: {
          type: Function // default: null
  
        },
        startWeekday: {
          // `0` (Sunday), `1` (Monday), ... `6` (Saturday)
          // Day of week to start calendar on
          type: [Number, String],
          default: 0
        },
        locale: {
          // Locale(s) to use
          // Default is to use page/browser default setting
          type: [String, Array] // default: null
  
        },
        direction: {
          // 'ltr', 'rtl', or `null` (for auto detect)
          type: String // default: null
  
        },
        selectedVariant: {
          // Variant color to use for the selected date
          type: String,
          default: 'primary'
        },
        todayVariant: {
          // Variant color to use for today's date (defaults to `variant`)
          type: String // default: null
  
        },
        noHighlightToday: {
          // Disable highlighting today's date
          type: Boolean,
          default: false
        },
        dateInfoFn: {
          // Function to set a class of (classes) on the date cell
          // if passed a string or an array
          // TODO:
          //   If the function returns an object, look for class prop for classes,
          //   and other props for handling events/details/descriptions
          type: Function // default: null
  
        },
        width: {
          // Has no effect if prop `block` is set
          type: String,
          default: '270px'
        },
        block: {
          // Makes calendar the full width of its parent container
          type: Boolean,
          default: false
        },
        hideHeader: {
          // When true makes the selected date header `sr-only`
          type: Boolean,
          default: false
        },
        hidden: {
          // When `true`, renders a comment node, but keeps the component instance active
          // Mainly for <b-form-date>, so that we can get the component's value and locale
          // But we might just use separate date formatters, using the resolved locale
          // (adjusted for the gregorian calendar)
          type: Boolean,
          default: false
        },
        ariaControls: {
          type: String // default: null
  
        },
        roleDescription: {
          type: String // default: null
  
        },
        // Labels for buttons and keyboard shortcuts
        labelPrevYear: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelPrevYear');
          }
        },
        labelPrevMonth: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelPrevMonth');
          }
        },
        labelCurrentMonth: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelCurrentMonth');
          }
        },
        labelNextMonth: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelNextMonth');
          }
        },
        labelNextYear: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelNextYear');
          }
        },
        labelToday: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelToday');
          }
        },
        labelSelected: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelSelected');
          }
        },
        labelNoDateSelected: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelNoDateSelected');
          }
        },
        labelCalendar: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelCalendar');
          }
        },
        labelNav: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelNav');
          }
        },
        labelHelp: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$6, 'labelHelp');
          }
        },
        dateFormatOptions: {
          // `Intl.DateTimeFormat` object
          type: Object,
          default: function _default() {
            return {
              year: 'numeric',
              month: 'long',
              day: 'numeric',
              weekday: 'long'
            };
          }
        }
      },
      data: function data() {
        var selected = formatYMD(this.value) || '';
        return {
          // Selected date
          selectedYMD: selected,
          // Date in calendar grid that has `tabindex` of `0`
          activeYMD: selected || formatYMD(this.getToday()),
          // Will be true if the calendar grid has/contains focus
          gridHasFocus: false,
          // Flag to enable the `aria-live` region(s) after mount
          // to prevent screen reader "outbursts" when mounting
          isLive: false
        };
      },
      computed: {
        // TODO: Use computed props to convert `YYYY-MM-DD` to `Date` object
        selectedDate: function selectedDate() {
          // Selected as a `Date` object
          return parseYMD(this.selectedYMD);
        },
        activeDate: function activeDate() {
          // Active as a `Date` object
          return parseYMD(this.activeYMD);
        },
        computedMin: function computedMin() {
          return parseYMD(this.min);
        },
        computedMax: function computedMax() {
          return parseYMD(this.max);
        },
        computedWeekStarts: function computedWeekStarts() {
          // `startWeekday` is a prop (constrained to `0` through `6`)
          return Math.max(toInteger(this.startWeekday) || 0, 0) % 7;
        },
        computedLocale: function computedLocale() {
          // Returns the resolved locale used by the calendar
          return resolveLocale(concat(this.locale).filter(identity), 'gregory');
        },
        calendarLocale: function calendarLocale() {
          // This locale enforces the gregorian calendar (for use in formatter functions)
          // Needed because IE 11 resolves `ar-IR` as islamic-civil calendar
          // and IE 11 (and some other browsers) do not support the `calendar` option
          // And we currently only support the gregorian calendar
          var fmt = new Intl.DateTimeFormat(this.computedLocale, {
            calendar: 'gregory'
          });
          var calendar = fmt.resolvedOptions().calendar;
          var locale = fmt.resolvedOptions().locale;
          /* istanbul ignore if: mainly for IE 11 and a few other browsers, hard to test in JSDOM */
  
          if (calendar !== 'gregory') {
            // Ensure the locale requests the gregorian calendar
            // Mainly for IE 11, and currently we can't handle non-gregorian calendars
            // TODO: Should we always return this value?
            locale = locale.replace(/-u-.+$/i, '').concat('-u-ca-gregory');
          }
  
          return locale;
        },
        calendarYear: function calendarYear() {
          return this.activeDate.getFullYear();
        },
        calendarMonth: function calendarMonth() {
          return this.activeDate.getMonth();
        },
        calendarFirstDay: function calendarFirstDay() {
          return createDate(this.calendarYear, this.calendarMonth, 1);
        },
        calendarDaysInMonth: function calendarDaysInMonth() {
          // We create a new date as to not mutate the original
          var date = createDate(this.calendarFirstDay);
          date.setMonth(date.getMonth() + 1, 0);
          return date.getDate();
        },
        computedVariant: function computedVariant() {
          return "btn-".concat(this.selectedVariant || 'primary');
        },
        computedTodayVariant: function computedTodayVariant() {
          return "btn-outline-".concat(this.todayVariant || this.selectedVariant || 'primary');
        },
        isRTL: function isRTL() {
          // `true` if the language requested is RTL
          var dir = toString$1(this.direction).toLowerCase();
  
          if (dir === 'rtl') {
            /* istanbul ignore next */
            return true;
          } else if (dir === 'ltr') {
            /* istanbul ignore next */
            return false;
          }
  
          return isLocaleRTL(this.computedLocale);
        },
        context: function context() {
          var selectedYMD = this.selectedYMD;
          var selectedDate = parseYMD(selectedYMD);
          var activeYMD = this.activeYMD;
          var activeDate = parseYMD(activeYMD);
          return {
            // The current value of the `v-model`
            selectedYMD: selectedYMD,
            selectedDate: selectedDate,
            selectedFormatted: selectedDate ? this.formatDateString(selectedDate) : this.labelNoDateSelected,
            // Which date cell is considered active due to navigation
            activeYMD: activeYMD,
            activeDate: activeDate,
            activeFormatted: activeDate ? this.formatDateString(activeDate) : '',
            // `true` if the date is disabled (when using keyboard navigation)
            disabled: this.dateDisabled(activeDate),
            // Locales used in formatting dates
            locale: this.computedLocale,
            calendarLocale: this.calendarLocale,
            rtl: this.isRTL
          };
        },
        // Computed props that return a function reference
        dateOutOfRange: function dateOutOfRange() {
          // Check wether a date is within the min/max range
          // returns a new function ref if the pops change
          // We do this as we need to trigger the calendar computed prop
          // to update when these props update
          var min = this.computedMin;
          var max = this.computedMax;
          return function (date) {
            // Handle both `YYYY-MM-DD` and `Date` objects
            date = parseYMD(date);
            return min && date < min || max && date > max;
          };
        },
        dateDisabled: function dateDisabled() {
          // Returns a function for validating if a date is within range
          // We grab this variables first to ensure a new function ref
          // is generated when the props value changes
          // We do this as we need to trigger the calendar computed prop
          // to update when these props update
          var rangeFn = this.dateOutOfRange;
          var disabledFn = isFunction(this.dateDisabledFn) ? this.dateDisabledFn : function () {
            return false;
          }; // Return the function ref
  
          return function (date) {
            // Handle both `YYYY-MM-DD` and `Date` objects
            date = parseYMD(date);
            var ymd = formatYMD(date);
            return !!(rangeFn(date) || disabledFn(ymd, date));
          };
        },
        // Computed props that return date formatter functions
        formatDateString: function formatDateString() {
          // Returns a date formatter function
          return createDateFormatter(this.calendarLocale, _objectSpread2({
            // Ensure we have year, month, day shown for screen readers/ARIA
            // If users really want to leave one of these out, they can
            // pass `undefined` for the property value
            year: 'numeric',
            month: '2-digit',
            day: '2-digit'
          }, this.dateFormatOptions, {
            // Ensure hours/minutes/seconds are not shown
            hour: undefined,
            minute: undefined,
            second: undefined,
            // Ensure calendar is gregorian
            calendar: 'gregory'
          }));
        },
        formatYearMonth: function formatYearMonth() {
          // Returns a date formatter function
          return createDateFormatter(this.calendarLocale, {
            year: 'numeric',
            month: 'long',
            calendar: 'gregory'
          });
        },
        formatWeekdayName: function formatWeekdayName() {
          return createDateFormatter(this.calendarLocale, {
            weekday: 'long',
            calendar: 'gregory'
          });
        },
        formatWeekdayNameShort: function formatWeekdayNameShort() {
          // Used as the header cells
          return createDateFormatter(this.calendarLocale, {
            weekday: 'short',
            calendar: 'gregory'
          });
        },
        formatDay: function formatDay() {
          return createDateFormatter(this.calendarLocale, {
            day: 'numeric',
            calendar: 'gregory'
          });
        },
        // Disabled states for the nav buttons
        prevYearDisabled: function prevYearDisabled() {
          var min = this.computedMin;
          return this.disabled || min && lastDateOfMonth(oneYearAgo(this.activeDate)) < min;
        },
        prevMonthDisabled: function prevMonthDisabled() {
          var min = this.computedMin;
          return this.disabled || min && lastDateOfMonth(oneMonthAgo(this.activeDate)) < min;
        },
        thisMonthDisabled: function thisMonthDisabled() {
          // TODO: We could/should check if today is out of range
          return this.disabled;
        },
        nextMonthDisabled: function nextMonthDisabled() {
          var max = this.computedMax;
          return this.disabled || max && firstDateOfMonth(oneMonthAhead(this.activeDate)) > max;
        },
        nextYearDisabled: function nextYearDisabled() {
          var max = this.computedMax;
          return this.disabled || max && firstDateOfMonth(oneYearAhead(this.activeDate)) > max;
        },
        // Calendar generation
        calendar: function calendar() {
          var matrix = [];
          var firstDay = this.calendarFirstDay;
          var calendarYear = firstDay.getFullYear();
          var calendarMonth = firstDay.getMonth();
          var daysInMonth = this.calendarDaysInMonth;
          var startIndex = firstDay.getDay(); // `0`..`6`
  
          var weekOffset = (this.computedWeekStarts > startIndex ? 7 : 0) - this.computedWeekStarts; // TODO: Change `dateInfoFn` to handle events and notes as well as classes
  
          var dateInfoFn = isFunction(this.dateInfoFn) ? this.dateInfoFn : function () {
            return {};
          }; // Build the calendar matrix
  
          var currentDay = 0 - weekOffset - startIndex;
  
          for (var week = 0; week < 6 && currentDay < daysInMonth; week++) {
            // For each week
            matrix[week] = []; // The following could be a map function
  
            for (var j = 0; j < 7; j++) {
              // For each day in week
              currentDay++;
              var date = createDate(calendarYear, calendarMonth, currentDay);
              var month = date.getMonth();
              var dayYMD = formatYMD(date);
              var dayDisabled = this.dateDisabled(date); // TODO: This could be a normalizer method
  
              var dateInfo = dateInfoFn(dayYMD, parseYMD(dayYMD));
              dateInfo = isString(dateInfo) || isArray(dateInfo) ? {
                class: dateInfo
              } : isPlainObject(dateInfo) ? _objectSpread2({
                class: ''
              }, dateInfo) : {
                class: ''
              };
              matrix[week].push({
                ymd: dayYMD,
                // Cell content
                day: this.formatDay(date),
                label: this.formatDateString(date),
                // Flags for styling
                isThisMonth: month === calendarMonth,
                isDisabled: dayDisabled,
                // TODO: Handle other dateInfo properties such as notes/events
                info: dateInfo
              });
            }
          }
  
          return matrix;
        },
        calendarHeadings: function calendarHeadings() {
          var _this = this;
  
          return this.calendar[0].map(function (d) {
            return {
              text: _this.formatWeekdayNameShort(parseYMD(d.ymd)),
              label: _this.formatWeekdayName(parseYMD(d.ymd))
            };
          });
        }
      },
      watch: {
        value: function value(newVal, oldVal) {
          var selected = formatYMD(newVal) || '';
          var old = formatYMD(oldVal) || '';
  
          if (!datesEqual(selected, old)) {
            this.activeYMD = selected || this.activeYMD;
            this.selectedYMD = selected;
          }
        },
        selectedYMD: function selectedYMD(newYMD, oldYMD) {
          // TODO:
          //   Should we compare to `formatYMD(this.value)` and emit
          //   only if they are different?
          if (newYMD !== oldYMD) {
            this.$emit('input', this.valueAsDate ? parseYMD(newYMD) || null : newYMD || '');
          }
        },
        context: function context(newVal, oldVal) {
          if (!looseEqual(newVal, oldVal)) {
            this.$emit('context', newVal);
          }
        },
        hidden: function hidden(newVal) {
          // Reset the active focused day when hidden
          this.activeYMD = this.selectedYMD || formatYMD(this.value) || formatYMD(this.getToday()); // Enable/disable the live regions
  
          this.setLive(!newVal);
        }
      },
      created: function created() {
        var _this2 = this;
  
        this.$nextTick(function () {
          _this2.$emit('context', _this2.context);
        });
      },
      mounted: function mounted() {
        this.setLive(true);
      },
      activated: function activated()
      /* istanbul ignore next */
      {
        this.setLive(true);
      },
      deactivated: function deactivated()
      /* istanbul ignore next */
      {
        this.setLive(false);
      },
      beforeDestroy: function beforeDestroy() {
        this.setLive(false);
      },
      methods: {
        // Public method(s)
        focus: function focus() {
          if (!this.disabled) {
            try {
              this.$refs.grid.focus();
            } catch (_unused) {}
          }
        },
        blur: function blur() {
          try {
            this.$refs.grid.blur();
          } catch (_unused2) {}
        },
        // Private methods
        setLive: function setLive(on) {
          var _this3 = this;
  
          if (on) {
            this.$nextTick(function () {
              requestAF(function () {
                _this3.isLive = true;
              });
            });
          } else {
            this.isLive = false;
          }
        },
        getToday: function getToday() {
          return parseYMD(createDate());
        },
        constrainDate: function constrainDate(date) {
          // Constrains a date between min and max
          // returns a new `Date` object instance
          date = parseYMD(date);
          var min = this.computedMin || date;
          var max = this.computedMax || date;
          return createDate(date < min ? min : date > max ? max : date);
        },
        emitSelected: function emitSelected(date) {
          var _this4 = this;
  
          // Performed in a `$nextTick()` to (probably) ensure
          // the input event has emitted first
          this.$nextTick(function () {
            _this4.$emit('selected', formatYMD(date) || '', parseYMD(date) || null);
          });
        },
        // Event handlers
        setGridFocusFlag: function setGridFocusFlag(evt) {
          // Sets the gridHasFocus flag to make date "button" look focused
          this.gridHasFocus = !this.disabled && evt.type === 'focus';
        },
        onKeydownWrapper: function onKeydownWrapper(evt) {
          // Calendar keyboard navigation
          // Handles PAGEUP/PAGEDOWN/END/HOME/LEFT/UP/RIGHT/DOWN
          // Focuses grid after updating
          var keyCode = evt.keyCode;
          var altKey = evt.altKey;
  
          if (!arrayIncludes([PAGEUP, PAGEDOWN, END, HOME, LEFT, UP, RIGHT, DOWN], keyCode)) {
            /* istanbul ignore next */
            return;
          }
  
          evt.preventDefault();
          evt.stopPropagation();
          var activeDate = createDate(this.activeDate);
          var checkDate = createDate(this.activeDate);
          var day = activeDate.getDate();
          var isRTL = this.isRTL;
  
          if (keyCode === PAGEUP) {
            // PAGEUP - Previous month/year
            activeDate = (altKey ? oneYearAgo : oneMonthAgo)(activeDate); // We check the first day of month to be in rage
  
            checkDate = createDate(activeDate);
            checkDate.setDate(1);
          } else if (keyCode === PAGEDOWN) {
            // PAGEDOWN - Next month/year
            activeDate = (altKey ? oneYearAhead : oneMonthAhead)(activeDate); // We check the last day of month to be in rage
  
            checkDate = createDate(activeDate);
            checkDate.setMonth(checkDate.getMonth() + 1);
            checkDate.setDate(0);
          } else if (keyCode === LEFT) {
            // LEFT - Previous day (or next day for RTL)
            activeDate.setDate(day + (isRTL ? 1 : -1));
            checkDate = activeDate;
          } else if (keyCode === RIGHT) {
            // RIGHT - Next day (or previous day for RTL)
            activeDate.setDate(day + (isRTL ? -1 : 1));
            checkDate = activeDate;
          } else if (keyCode === UP) {
            // UP - Previous week
            activeDate.setDate(day - 7);
            checkDate = activeDate;
          } else if (keyCode === DOWN) {
            // DOWN - Next week
            activeDate.setDate(day + 7);
            checkDate = activeDate;
          } else if (keyCode === HOME) {
            // HOME - Today
            activeDate = this.getToday();
            checkDate = activeDate;
          } else if (keyCode === END) {
            // END - Selected date, or today if no selected date
            activeDate = parseYMD(this.selectedDate) || this.getToday();
            checkDate = activeDate;
          }
  
          if (!this.dateOutOfRange(checkDate) && !datesEqual(activeDate, this.activeDate)) {
            // We only jump to date if within min/max
            // We don't check for individual disabled dates though (via user function)
            this.activeYMD = formatYMD(activeDate);
          } // Ensure grid is focused
  
  
          this.focus();
        },
        onKeydownGrid: function onKeydownGrid(evt) {
          // Pressing enter/space on grid to select active date
          var keyCode = evt.keyCode;
          var activeDate = this.activeDate;
  
          if (keyCode === ENTER || keyCode === SPACE) {
            evt.preventDefault();
            evt.stopPropagation();
  
            if (!this.disabled && !this.readonly && !this.dateDisabled(activeDate)) {
              this.selectedYMD = formatYMD(activeDate);
              this.emitSelected(activeDate);
            } // Ensure grid is focused
  
  
            this.focus();
          }
        },
        onClickDay: function onClickDay(day) {
          // Clicking on a date "button" to select it
          var selectedDate = this.selectedDate;
          var activeDate = this.activeDate;
          var clickedDate = parseYMD(day.ymd);
  
          if (!this.disabled && !day.isDisabled && !this.dateDisabled(clickedDate)) {
            if (!this.readonly) {
              // If readonly mode, we don't set the selected date, just the active date
              // If the clicked date is equal to the already selected date, we don't update the model
              this.selectedYMD = formatYMD(datesEqual(clickedDate, selectedDate) ? selectedDate : clickedDate);
              this.emitSelected(clickedDate);
            }
  
            this.activeYMD = formatYMD(datesEqual(clickedDate, activeDate) ? activeDate : createDate(clickedDate)); // Ensure grid is focused
  
            this.focus();
          }
        },
        gotoPrevYear: function gotoPrevYear() {
          this.activeYMD = formatYMD(this.constrainDate(oneYearAgo(this.activeDate)));
        },
        gotoPrevMonth: function gotoPrevMonth() {
          this.activeYMD = formatYMD(this.constrainDate(oneMonthAgo(this.activeDate)));
        },
        gotoCurrentMonth: function gotoCurrentMonth() {
          // TODO: Maybe this goto date should be configurable?
          this.activeYMD = formatYMD(this.getToday());
        },
        gotoNextMonth: function gotoNextMonth() {
          this.activeYMD = formatYMD(this.constrainDate(oneMonthAhead(this.activeDate)));
        },
        gotoNextYear: function gotoNextYear() {
          this.activeYMD = formatYMD(this.constrainDate(oneYearAhead(this.activeDate)));
        },
        onHeaderClick: function onHeaderClick() {
          if (!this.disabled) {
            this.activeYMD = this.selectedYMD || formatYMD(this.getToday());
            this.focus();
          }
        }
      },
      render: function render(h) {
        var _this5 = this;
  
        // If hidden prop is set, render just a placeholder node
        if (this.hidden) {
          return h();
        }
  
        var isRTL = this.isRTL;
        var todayYMD = formatYMD(this.getToday());
        var selectedYMD = this.selectedYMD;
        var activeYMD = this.activeYMD;
        var highlightToday = !this.noHighlightToday;
        var safeId = this.safeId; // Flag for making the `aria-live` regions live
  
        var isLive = this.isLive; // Pre-compute some IDs
        // Thes should be computed props
  
        var idValue = safeId();
        var idWidget = safeId('_calendar-wrapper_');
        var idNav = safeId('_calendar-nav_');
        var idGrid = safeId('_calendar-grid_');
        var idGridCaption = safeId('_calendar-grid-caption_');
        var idGridHelp = safeId('_calendar-grid-help_');
        var idActive = activeYMD ? safeId("_cell-".concat(activeYMD, "_")) : null; // Header showing current selected date
  
        var $header = h('output', {
          staticClass: 'd-block text-center rounded border small p-1 mb-1',
          class: {
            'text-muted': this.disabled,
            readonly: this.readonly || this.disabled
          },
          attrs: {
            id: idValue,
            for: idGrid,
            role: 'status',
            tabindex: this.disabled ? null : '-1',
            // Mainly for testing purposes, as we do not know
            // the exact format `Intl` will format the date string
            'data-selected': toString$1(selectedYMD),
            // We wait until after mount to enable `aria-live`
            // to prevent initial announcement on page render
            'aria-live': isLive ? 'polite' : 'off',
            'aria-atomic': isLive ? 'true' : null
          },
          on: {
            // Transfer focus/click to focus grid
            // and focus active date (or today if no selection)
            click: this.onHeaderClick,
            focus: this.onHeaderClick
          }
        }, this.selectedDate ? [// We use `bdi` elements here in case the label doesn't match the locale
        // Although IE 11 does not deal with <BDI> at all (equivalent to a span)
        h('bdi', {
          staticClass: 'sr-only'
        }, " (".concat(toString$1(this.labelSelected), ") ")), h('bdi', {}, this.formatDateString(this.selectedDate))] : this.labelNoDateSelected || "\xA0" // '&nbsp;'
        );
        $header = h('header', {
          class: this.hideHeader ? 'sr-only' : 'mb-1',
          attrs: {
            title: this.selectedDate ? this.labelSelectedDate || null : null
          }
        }, [$header]); // Content for the date navigation buttons
  
        var $prevYearIcon = h(BIconstack, {
          props: {
            shiftV: 0.5,
            flipH: isRTL
          }
        }, [h(BIconChevronLeft, {
          props: {
            shiftH: -2
          }
        }), h(BIconChevronLeft, {
          props: {
            shiftH: 2
          }
        })]);
        var $prevMonthIcon = h(BIconChevronLeft, {
          props: {
            shiftV: 0.5,
            flipH: isRTL
          }
        });
        var $thisMonthIcon = h(BIconCircleFill, {
          props: {
            shiftV: 0.5
          }
        });
        var $nextMonthIcon = h(BIconChevronLeft, {
          props: {
            shiftV: 0.5,
            flipH: !isRTL
          }
        });
        var $nextYearIcon = h(BIconstack, {
          props: {
            shiftV: 0.5,
            flipH: !isRTL
          }
        }, [h(BIconChevronLeft, {
          props: {
            shiftH: -2
          }
        }), h(BIconChevronLeft, {
          props: {
            shiftH: 2
          }
        })]); // Utility to create the date navigation buttons
  
        var makeNavBtn = function makeNavBtn(content, label, handler, btnDisabled, shortcut) {
          return h('button', {
            staticClass: 'btn btn-sm btn-outline-secondary border-0 flex-fill p-1 mx-1',
            class: {
              disabled: btnDisabled
            },
            attrs: {
              title: label || null,
              type: 'button',
              'aria-label': label || null,
              'aria-disabled': btnDisabled ? 'true' : null,
              'aria-keyshortcuts': shortcut || null
            },
            on: btnDisabled ? {} : {
              click: handler
            }
          }, [h('div', {
            attrs: {
              'aria-hidden': 'true'
            }
          }, [content])]);
        }; // Generate the date navigation buttons
  
  
        var $nav = h('div', {
          staticClass: 'b-calendar-nav d-flex mx-n1 mb-1',
          attrs: {
            id: idNav,
            role: 'group',
            'aria-hidden': this.disabled ? 'true' : null,
            'aria-label': this.labelNav || null,
            'aria-controls': idGrid
          }
        }, [makeNavBtn($prevYearIcon, this.labelPrevYear, this.gotoPrevYear, this.prevYearDisabled, 'Alt+PageDown'), makeNavBtn($prevMonthIcon, this.labelPrevMonth, this.gotoPrevMonth, this.prevMonthDisabled, 'PageDown'), makeNavBtn($thisMonthIcon, this.labelCurrentMonth, this.gotoCurrentMonth, this.thisMonthDisabled, 'Home'), makeNavBtn($nextMonthIcon, this.labelNextMonth, this.gotoNextMonth, this.nextMonthDisabled, 'PageUp'), makeNavBtn($nextYearIcon, this.labelNextYear, this.gotoNextYear, this.nextYearDisabled, 'Alt+PageUp')]); // Caption for calendar grid
  
        var $gridCaption = h('header', {
          key: 'grid-caption',
          staticClass: 'text-center font-weight-bold p-1 m-0',
          class: {
            'text-muted': this.disabled
          },
          attrs: {
            id: idGridCaption,
            'aria-live': isLive ? 'polite' : null,
            'aria-atomic': isLive ? 'true' : null
          }
        }, this.formatYearMonth(this.calendarFirstDay)); // Calendar weekday headings
  
        var $gridWeekDays = h('div', {
          staticClass: 'row no-gutters border-bottom',
          attrs: {
            'aria-hidden': 'true'
          }
        }, this.calendarHeadings.map(function (d, idx) {
          return h('small', {
            key: idx,
            staticClass: 'col text-truncate',
            class: {
              'text-muted': _this5.disabled
            },
            attrs: {
              title: d.label === d.text ? null : d.label,
              'aria-label': d.label
            }
          }, d.text);
        })); // Calendar day grid
  
        var $gridBody = this.calendar.map(function (week) {
          var $cells = week.map(function (day, dIndex) {
            var _class;
  
            var isSelected = day.ymd === selectedYMD;
            var isActive = day.ymd === activeYMD;
            var isToday = day.ymd === todayYMD;
            var idCell = safeId("_cell-".concat(day.ymd, "_")); // "fake" button
  
            var $btn = h('span', {
              staticClass: 'btn border-0 rounded-circle text-nowrap',
              // Should we add some classes to signify if today/selected/etc?
              class: (_class = {
                // Give the fake button a focus ring
                focus: isActive && _this5.gridHasFocus,
                // Styling
                disabled: day.isDisabled || _this5.disabled,
                active: isSelected
              }, _defineProperty(_class, _this5.computedVariant, isSelected), _defineProperty(_class, _this5.computedTodayVariant, isToday && highlightToday && !isSelected && day.isThisMonth), _defineProperty(_class, 'btn-outline-light', !(isToday && highlightToday) && !isSelected && !isActive), _defineProperty(_class, 'btn-light', !(isToday && highlightToday) && !isSelected && isActive), _defineProperty(_class, 'text-muted', !day.isThisMonth && !isSelected), _defineProperty(_class, 'text-dark', !(isToday && highlightToday) && !isSelected && !isActive && day.isThisMonth), _defineProperty(_class, 'font-weight-bold', (isSelected || day.isThisMonth) && !day.isDisabled), _class),
              on: {
                click: function click() {
                  return _this5.onClickDay(day);
                }
              }
            }, day.day);
            return h('div', // Cell with button
            {
              key: dIndex,
              staticClass: 'col p-0',
              class: day.isDisabled ? 'bg-light' : day.info.class || '',
              attrs: {
                id: idCell,
                role: 'button',
                'data-date': day.ymd,
                // Primarily for testing purposes
                // Only days in the month are presented as buttons to screen readers
                'aria-hidden': day.isThisMonth ? null : 'true',
                'aria-disabled': day.isDisabled || _this5.disabled ? 'true' : null,
                'aria-label': [day.label, isSelected ? "(".concat(_this5.labelSelected, ")") : null, isToday ? "(".concat(_this5.labelToday, ")") : null].filter(identity).join(' '),
                // NVDA doesn't convey `aria-selected`, but does `aria-current`,
                // ChromeVox doesn't convey `aria-current`, but does `aria-selected`,
                // so we set both attributes for robustness
                'aria-selected': isSelected ? 'true' : null,
                'aria-current': isSelected ? 'date' : null
              }
            }, [$btn]);
          }); // Return the week "row"
          // We use the first day of the weeks YMD value as a
          // key for efficient DOM patching / element re-use
  
          return h('div', {
            key: week[0].ymd,
            staticClass: 'row no-gutters'
          }, $cells);
        });
        $gridBody = h('div', {
          // A key is only required on the body if we add in transition support
          // key: this.activeYMD.slice(0, -3),
          staticClass: 'b-calendar-grid-body',
          style: this.disabled ? {
            pointerEvents: 'none'
          } : {}
        }, $gridBody);
        var $gridHelp = h('footer', {
          staticClass: 'border-top small text-muted text-center bg-light',
          attrs: {
            id: idGridHelp
          }
        }, [h('div', {
          staticClass: 'small'
        }, this.labelHelp)]);
        var $grid = h('div', {
          ref: 'grid',
          staticClass: 'form-control h-auto text-center p-0 mb-0',
          attrs: {
            id: idGrid,
            role: 'application',
            tabindex: this.disabled ? null : '0',
            'data-month': activeYMD.slice(0, -3),
            // `YYYY-MM`, mainly for testing
            'aria-roledescription': this.labelCalendar || null,
            'aria-labelledby': idGridCaption,
            'aria-describedby': idGridHelp,
            // `aria-readonly` is not considered valid on `role="application"`
            // https://www.w3.org/TR/wai-aria-1.1/#aria-readonly
            // 'aria-readonly': this.readonly && !this.disabled ? 'true' : null,
            'aria-disabled': this.disabled ? 'true' : null,
            'aria-activedescendant': idActive
          },
          on: {
            keydown: this.onKeydownGrid,
            focus: this.setGridFocusFlag,
            blur: this.setGridFocusFlag
          }
        }, [$gridCaption, $gridWeekDays, $gridBody, $gridHelp]); // Optional bottom slot
  
        var $slot = this.normalizeSlot('default');
        $slot = $slot ? h('footer', {
          staticClass: 'mt-2'
        }, $slot) : h();
        var $widget = h('div', {
          staticClass: 'b-calendar-inner',
          class: this.block ? 'd-block' : 'd-inline-block',
          style: this.block ? {} : {
            width: this.width
          },
          attrs: {
            id: idWidget,
            dir: isRTL ? 'rtl' : 'ltr',
            lang: this.computedLocale || null,
            role: 'group',
            'aria-disabled': this.disabled ? 'true' : null,
            // If datepicker controls an input, this will specify the ID of the input
            'aria-controls': this.ariaControls || null,
            // This should be a prop (so it can be changed to Date picker, etc, localized
            'aria-roledescription': this.roleDescription || null,
            'aria-describedby': [// Should the attr (if present) go last?
            // Or should this attr be a prop?
            this.$attrs['aria-describedby'], idValue, idGridHelp].filter(identity).join(' ')
          },
          on: {
            keydown: this.onKeydownWrapper
          }
        }, [$header, $nav, $grid, $slot]); // Wrap in an outer div that can be styled
  
        return h('div', {
          staticClass: 'b-calendar',
          // We use a style here rather than class `d-inline-block` so that users can
          // override the display value (`d-*` classes use the `!important` flag)
          style: this.block ? {} : {
            display: 'inline-block'
          }
        }, [$widget]);
      }
    });
  
    var CalendarPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BCalendar: BCalendar
      }
    });
  
    /**
     * @param {string} prefix
     * @param {string} value
     */
  
    var prefixPropName = function prefixPropName(prefix, value) {
      return prefix + upperFirst(value);
    };
  
    /**
     * @param {string} prefix
     * @param {string} value
     */
  
    var unprefixPropName = function unprefixPropName(prefix, value) {
      return lowerFirst(value.replace(prefix, ''));
    };
  
    /**
     * Copies props from one array/object to a new array/object. Prop values
     * are also cloned as new references to prevent possible mutation of original
     * prop object values. Optionally accepts a function to transform the prop name.
     *
     * @param {[]|{}} props
     * @param {Function} transformFn
     */
  
    var copyProps = 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) {
        /* istanbul ignore else */
        // eslint-disable-next-line no-prototype-builtins
        if (props.hasOwnProperty(prop)) {
          // If the prop value is an object, do a shallow clone to prevent
          // potential mutations to the original object.
          copied[transformFn(prop)] = isObject(props[prop]) ? clone(props[prop]) : props[prop];
        }
      }
  
      return copied;
    };
  
    // @vue/component
    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$6 = {
      title: {
        type: String,
        default: ''
      },
      titleTag: {
        type: String,
        default: 'h4'
      }
    }; // @vue/component
  
    var BCardTitle = /*#__PURE__*/Vue.extend({
      name: 'BCardTitle',
      functional: true,
      props: props$6,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.titleTag, a(data, {
          staticClass: 'card-title'
        }), children || props.title);
      }
    });
  
    var NAME$7 = 'BCardSubTitle';
    var props$7 = {
      subTitle: {
        type: String,
        default: ''
      },
      subTitleTag: {
        type: String,
        default: 'h6'
      },
      subTitleTextVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$7, 'subTitleTextVariant');
        }
      }
    }; // @vue/component
  
    var BCardSubTitle = /*#__PURE__*/Vue.extend({
      name: NAME$7,
      functional: true,
      props: props$7,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.subTitleTag, a(data, {
          staticClass: 'card-subtitle',
          class: [props.subTitleTextVariant ? "text-".concat(props.subTitleTextVariant) : null]
        }), children || props.subTitle);
      }
    });
  
    var props$8 = _objectSpread2({}, copyProps(cardMixin.props, prefixPropName.bind(null, 'body')), {
      bodyClass: {
        type: [String, Object, Array],
        default: null
      }
    }, props$6, {}, props$7, {
      overlay: {
        type: Boolean,
        default: false
      }
    }); // @vue/component
  
    var BCardBody = /*#__PURE__*/Vue.extend({
      name: 'BCardBody',
      functional: true,
      props: props$8,
      render: function render(h, _ref) {
        var _ref2;
  
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var cardTitle = h();
        var cardSubTitle = h();
        var cardContent = children || [h()];
  
        if (props.title) {
          cardTitle = h(BCardTitle, {
            props: pluckProps(props$6, props)
          });
        }
  
        if (props.subTitle) {
          cardSubTitle = h(BCardSubTitle, {
            props: pluckProps(props$7, props),
            class: ['mb-2']
          });
        }
  
        return h(props.bodyTag, a(data, {
          staticClass: 'card-body',
          class: [(_ref2 = {
            'card-img-overlay': props.overlay
          }, _defineProperty(_ref2, "bg-".concat(props.bodyBgVariant), props.bodyBgVariant), _defineProperty(_ref2, "border-".concat(props.bodyBorderVariant), props.bodyBorderVariant), _defineProperty(_ref2, "text-".concat(props.bodyTextVariant), props.bodyTextVariant), _ref2), props.bodyClass || {}]
        }), [cardTitle, cardSubTitle].concat(_toConsumableArray(cardContent)));
      }
    });
  
    var props$9 = _objectSpread2({}, copyProps(cardMixin.props, prefixPropName.bind(null, 'header')), {
      header: {
        type: String,
        default: null
      },
      headerHtml: {
        type: String,
        default: null
      },
      headerClass: {
        type: [String, Object, Array],
        default: null
      }
    }); // @vue/component
  
    var BCardHeader = /*#__PURE__*/Vue.extend({
      name: 'BCardHeader',
      functional: true,
      props: props$9,
      render: function render(h, _ref) {
        var _ref2;
  
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.headerTag, a(data, {
          staticClass: 'card-header',
          class: [props.headerClass, (_ref2 = {}, _defineProperty(_ref2, "bg-".concat(props.headerBgVariant), props.headerBgVariant), _defineProperty(_ref2, "border-".concat(props.headerBorderVariant), props.headerBorderVariant), _defineProperty(_ref2, "text-".concat(props.headerTextVariant), props.headerTextVariant), _ref2)]
        }), children || [h('div', {
          domProps: htmlOrText(props.headerHtml, props.header)
        })]);
      }
    });
  
    var props$a = _objectSpread2({}, copyProps(cardMixin.props, prefixPropName.bind(null, 'footer')), {
      footer: {
        type: String,
        default: null
      },
      footerHtml: {
        type: String,
        default: null
      },
      footerClass: {
        type: [String, Object, Array],
        default: null
      }
    }); // @vue/component
  
    var BCardFooter = /*#__PURE__*/Vue.extend({
      name: 'BCardFooter',
      functional: true,
      props: props$a,
      render: function render(h, _ref) {
        var _ref2;
  
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.footerTag, a(data, {
          staticClass: 'card-footer',
          class: [props.footerClass, (_ref2 = {}, _defineProperty(_ref2, "bg-".concat(props.footerBgVariant), props.footerBgVariant), _defineProperty(_ref2, "border-".concat(props.footerBorderVariant), props.footerBorderVariant), _defineProperty(_ref2, "text-".concat(props.footerTextVariant), props.footerTextVariant), _ref2)]
        }), children || [h('div', {
          domProps: htmlOrText(props.footerHtml, props.footer)
        })]);
      }
    });
  
    var props$b = {
      src: {
        type: String,
        default: null,
        required: true
      },
      alt: {
        type: String,
        default: null
      },
      top: {
        type: Boolean,
        default: false
      },
      bottom: {
        type: Boolean,
        default: false
      },
      start: {
        type: Boolean,
        default: false
      },
      left: {
        // alias of 'start'
        type: Boolean,
        default: false
      },
      end: {
        type: Boolean,
        default: false
      },
      right: {
        // alias of 'end'
        type: Boolean,
        default: false
      },
      height: {
        type: [Number, String],
        default: null
      },
      width: {
        type: [Number, String],
        default: null
      }
    }; // @vue/component
  
    var BCardImg = /*#__PURE__*/Vue.extend({
      name: 'BCardImg',
      functional: true,
      props: props$b,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data;
        var baseClass = 'card-img';
  
        if (props.top) {
          baseClass += '-top';
        } else if (props.right || props.end) {
          baseClass += '-right';
        } else if (props.bottom) {
          baseClass += '-bottom';
        } else if (props.left || props.start) {
          baseClass += '-left';
        }
  
        return h('img', a(data, {
          class: [baseClass],
          attrs: {
            src: props.src,
            alt: props.alt,
            height: props.height,
            width: props.width
          }
        }));
      }
    });
  
    var cardImgProps = copyProps(props$b, prefixPropName.bind(null, 'img'));
    cardImgProps.imgSrc.required = false;
    var props$c = _objectSpread2({}, props$8, {}, props$9, {}, props$a, {}, cardImgProps, {}, copyProps(cardMixin.props), {
      align: {
        type: String,
        default: null
      },
      noBody: {
        type: Boolean,
        default: false
      }
    }); // @vue/component
  
    var BCard = /*#__PURE__*/Vue.extend({
      name: 'BCard',
      functional: true,
      props: props$c,
      render: function render(h, _ref) {
        var _class;
  
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots;
        var $slots = slots(); // Vue < 2.6.x may return undefined for scopedSlots
  
        var $scopedSlots = scopedSlots || {}; // Create placeholder elements for each section
  
        var imgFirst = h();
        var header = h();
        var content = h();
        var footer = h();
        var imgLast = h();
  
        if (props.imgSrc) {
          var img = h(BCardImg, {
            props: pluckProps(cardImgProps, props, unprefixPropName.bind(null, 'img'))
          });
  
          if (props.imgBottom) {
            imgLast = img;
          } else {
            imgFirst = img;
          }
        }
  
        if (props.header || hasNormalizedSlot('header', $scopedSlots, $slots)) {
          header = h(BCardHeader, {
            props: pluckProps(props$9, props)
          }, normalizeSlot('header', {}, $scopedSlots, $slots));
        }
  
        content = normalizeSlot('default', {}, $scopedSlots, $slots) || [];
  
        if (!props.noBody) {
          // Wrap content in card-body
          content = [h(BCardBody, {
            props: pluckProps(props$8, props)
          }, _toConsumableArray(content))];
        }
  
        if (props.footer || hasNormalizedSlot('footer', $scopedSlots, $slots)) {
          footer = h(BCardFooter, {
            props: pluckProps(props$a, props)
          }, normalizeSlot('footer', {}, $scopedSlots, $slots));
        }
  
        return h(props.tag, a(data, {
          staticClass: 'card',
          class: (_class = {
            'flex-row': props.imgLeft || props.imgStart,
            'flex-row-reverse': (props.imgRight || props.imgEnd) && !(props.imgLeft || props.imgStart)
          }, _defineProperty(_class, "text-".concat(props.align), props.align), _defineProperty(_class, "bg-".concat(props.bgVariant), props.bgVariant), _defineProperty(_class, "border-".concat(props.borderVariant), props.borderVariant), _defineProperty(_class, "text-".concat(props.textVariant), props.textVariant), _class)
        }), [imgFirst, header].concat(_toConsumableArray(content), [footer, imgLast]));
      }
    });
  
    var OBSERVER_PROP_NAME = '__bv__visibility_observer';
    var onlyDgitsRE = /^\d+$/;
  
    var VisibilityObserver = /*#__PURE__*/function () {
      function VisibilityObserver(el, options, vnode) {
        _classCallCheck(this, VisibilityObserver);
  
        this.el = el;
        this.callback = options.callback;
        this.margin = options.margin || 0;
        this.once = options.once || false;
        this.observer = null;
        this.visible = undefined;
        this.doneOnce = false; // Create the observer instance (if possible)
  
        this.createObserver(vnode);
      }
  
      _createClass(VisibilityObserver, [{
        key: "createObserver",
        value: function createObserver(vnode) {
          var _this = this;
  
          // Remove any previous observer
          if (this.observer) {
            /* istanbul ignore next */
            this.stop();
          } // Should only be called once and `callback` prop should be a function
  
  
          if (this.doneOnce || !isFunction(this.callback)) {
            /* istanbul ignore next */
            return;
          } // Create the observer instance
  
  
          try {
            // Future: Possibly add in other modifiers for left/right/top/bottom
            // offsets, root element reference, and thresholds
            this.observer = new IntersectionObserver(this.handler.bind(this), {
              // `null` = 'viewport'
              root: null,
              // Pixels away from view port to consider "visible"
              rootMargin: this.margin,
              // Intersection ratio of el and root (as a value from 0 to 1)
              threshold: 0
            });
          } catch (_unused) {
            // No IntersectionObserver support, so just stop trying to observe
            this.doneOnce = true;
            this.observer = undefined;
            this.callback(null);
            return;
          } // Start observing in a `$nextTick()` (to allow DOM to complete rendering)
  
          /* istanbul ignore next: IntersectionObserver not supported in JSDOM */
  
  
          vnode.context.$nextTick(function () {
            requestAF(function () {
              // Placed in an `if` just in case we were destroyed before
              // this `requestAnimationFrame` runs
              if (_this.observer) {
                _this.observer.observe(_this.el);
              }
            });
          });
        }
      }, {
        key: "handler",
        value: function handler(entries)
        /* istanbul ignore next: IntersectionObserver not supported in JSDOM */
        {
          var entry = entries ? entries[0] : {};
          var isIntersecting = Boolean(entry.isIntersecting || entry.intersectionRatio > 0.0);
  
          if (isIntersecting !== this.visible) {
            this.visible = isIntersecting;
            this.callback(isIntersecting);
  
            if (this.once && this.visible) {
              this.doneOnce = true;
              this.stop();
            }
          }
        }
      }, {
        key: "stop",
        value: function stop() {
          var observer = this.observer;
          /* istanbul ignore next */
  
          if (observer && observer.disconnect) {
            observer.disconnect();
          }
  
          this.observer = null;
        }
      }]);
  
      return VisibilityObserver;
    }();
  
    var destroy = function destroy(el) {
      var observer = el[OBSERVER_PROP_NAME];
  
      if (observer && observer.stop) {
        observer.stop();
      }
  
      delete el[OBSERVER_PROP_NAME];
    };
  
    var bind = function bind(el, _ref, vnode) {
      var value = _ref.value,
          modifiers = _ref.modifiers;
      // `value` is the callback function
      var options = {
        margin: '0px',
        once: false,
        callback: value
      }; // Parse modifiers
  
      keys(modifiers).forEach(function (mod) {
        /* istanbul ignore else: Until <b-img-lazy> is switched to use this directive */
        if (onlyDgitsRE.test(mod)) {
          options.margin = "".concat(mod, "px");
        } else if (mod.toLowerCase() === 'once') {
          options.once = true;
        }
      }); // Destroy any previous observer
  
      destroy(el); // Create new observer
  
      el[OBSERVER_PROP_NAME] = new VisibilityObserver(el, options, vnode); // Store the current modifiers on the object (cloned)
  
      el[OBSERVER_PROP_NAME]._prevModifiers = clone(modifiers);
    }; // When the directive options may have been updated (or element)
  
  
    var componentUpdated = function componentUpdated(el, _ref2, vnode) {
      var value = _ref2.value,
          oldValue = _ref2.oldValue,
          modifiers = _ref2.modifiers;
      // Compare value/oldValue and modifiers to see if anything has changed
      // and if so, destroy old observer and create new observer
  
      /* istanbul ignore next */
      modifiers = clone(modifiers);
      /* istanbul ignore next */
  
      if (el && (value !== oldValue || !el[OBSERVER_PROP_NAME] || !looseEqual(modifiers, el[OBSERVER_PROP_NAME]._prevModifiers))) {
        // Re-bind on element
        bind(el, {
          value: value,
          modifiers: modifiers
        }, vnode);
      }
    }; // When directive un-binds from element
  
  
    var unbind = function unbind(el) {
      // Remove the observer
      destroy(el);
    }; // Export the directive
  
  
    var VBVisible = {
      bind: bind,
      componentUpdated: componentUpdated,
      unbind: unbind
    };
  
    var NAME$8 = 'BImg'; // Blank image with fill template
  
    var BLANK_TEMPLATE = '<svg width="%{w}" height="%{h}" ' + 'xmlns="http://www.w3.org/2000/svg" ' + 'viewBox="0 0 %{w} %{h}" preserveAspectRatio="none">' + '<rect width="100%" height="100%" style="fill:%{f};"></rect>' + '</svg>';
    var props$d = {
      src: {
        type: String,
        default: null
      },
      srcset: {
        type: [String, Array],
        default: null
      },
      sizes: {
        type: [String, Array],
        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: function _default() {
          return getComponentConfig(NAME$8, 'blankColor');
        }
      }
    }; // --- Helper methods ---
  
    var makeBlankImgSrc = function makeBlankImgSrc(width, height, color) {
      var src = encodeURIComponent(BLANK_TEMPLATE.replace('%{w}', toString$1(width)).replace('%{h}', toString$1(height)).replace('%{f}', color));
      return "data:image/svg+xml;charset=UTF-8,".concat(src);
    }; // @vue/component
  
  
    var BImg = /*#__PURE__*/Vue.extend({
      name: NAME$8,
      functional: true,
      props: props$d,
      render: function render(h, _ref) {
        var _class;
  
        var props = _ref.props,
            data = _ref.data;
        var src = props.src;
        var width = toInteger(props.width) || null;
        var height = toInteger(props.height) || null;
        var align = null;
        var block = props.block;
        var srcset = concat(props.srcset).filter(identity).join(',');
        var sizes = concat(props.sizes).filter(identity).join(',');
  
        if (props.blank) {
          if (!height && width) {
            height = width;
          } else if (!width && height) {
            width = height;
          }
  
          if (!width && !height) {
            width = 1;
            height = 1;
          } // Make a blank SVG image
  
  
          src = makeBlankImgSrc(width, height, props.blankColor || 'transparent'); // Disable srcset and sizes
  
          srcset = null;
          sizes = null;
        }
  
        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', a(data, {
          attrs: {
            src: src,
            alt: props.alt,
            width: width ? toString$1(width) : null,
            height: height ? toString$1(height) : null,
            srcset: srcset || null,
            sizes: sizes || 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-".concat(props.rounded), isString(props.rounded) && props.rounded !== ''), _defineProperty(_class, align, align), _defineProperty(_class, 'd-block', block), _class)
        }));
      }
    });
  
    var NAME$9 = 'BImgLazy';
    var props$e = {
      src: {
        type: String,
        default: null,
        required: true
      },
      srcset: {
        type: [String, Array],
        default: null
      },
      sizes: {
        type: [String, Array],
        default: null
      },
      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: function _default() {
          return getComponentConfig(NAME$9, 'blankColor');
        }
      },
      blankWidth: {
        type: [Number, String],
        default: null
      },
      blankHeight: {
        type: [Number, String],
        default: null
      },
      show: {
        type: Boolean,
        default: false
      },
      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: {
        // Distance away from viewport (in pixels) before being
        // considered "visible"
        type: [Number, String],
        default: 360
      }
    }; // @vue/component
  
    var BImgLazy = /*#__PURE__*/Vue.extend({
      name: NAME$9,
      directives: {
        bVisible: VBVisible
      },
      props: props$e,
      data: function data() {
        return {
          isShown: this.show
        };
      },
      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;
        },
        computedSrcset: function computedSrcset() {
          var srcset = concat(this.srcset).filter(identity).join(',');
          return !this.blankSrc || this.isShown ? srcset : null;
        },
        computedSizes: function computedSizes() {
          var sizes = concat(this.sizes).filter(identity).join(',');
          return !this.blankSrc || this.isShown ? sizes : null;
        }
      },
      watch: {
        show: function show(newVal, oldVal) {
          if (newVal !== oldVal) {
            // If IntersectionObserver support is not available, image is always shown
            var visible = hasIntersectionObserverSupport ? newVal : true;
            this.isShown = visible;
  
            if (visible !== newVal) {
              // Ensure the show prop is synced (when no IntersectionObserver)
              this.$nextTick(this.updateShowProp);
            }
          }
        },
        isShown: function isShown(newVal, oldVal) {
          if (newVal !== oldVal) {
            // Update synched show prop
            this.updateShowProp();
          }
        }
      },
      mounted: function mounted() {
        // If IntersectionObserver is not available, image is always shown
        this.isShown = hasIntersectionObserverSupport ? this.show : true;
      },
      methods: {
        updateShowProp: function updateShowProp() {
          this.$emit('update:show', this.isShown);
        },
        doShow: function doShow(visible) {
          // If IntersectionObserver is not supported, the callback
          // will be called with `null` rather than `true` or `false`
          if ((visible || visible === null) && !this.isShown) {
            this.isShown = true;
          }
        }
      },
      render: function render(h) {
        var directives = [];
  
        if (!this.isShown) {
          var _modifiers;
  
          // We only add the visible directive if we are not shown
          directives.push({
            // Visible directive will silently do nothing if
            // IntersectionObserver is not supported
            name: 'b-visible',
            // Value expects a callback (passed one arg of `visible` = `true` or `false`)
            value: this.doShow,
            modifiers: (_modifiers = {}, _defineProperty(_modifiers, "".concat(toInteger(this.offset) || 0), true), _defineProperty(_modifiers, "once", true), _modifiers)
          });
        }
  
        return h(BImg, {
          directives: directives,
          props: {
            // Computed value props
            src: this.computedSrc,
            blank: this.computedBlank,
            width: this.computedWidth,
            height: this.computedHeight,
            srcset: this.computedSrcset || null,
            sizes: this.computedSizes || null,
            // Passthrough props
            alt: this.alt,
            blankColor: this.blankColor,
            fluid: this.fluid,
            fluidGrow: this.fluidGrow,
            block: this.block,
            thumbnail: this.thumbnail,
            rounded: this.rounded,
            left: this.left,
            right: this.right,
            center: this.center
          }
        });
      }
    });
  
    // The `omit()` util creates a new object, so we can just pass the original props
  
    var lazyProps = omit(props$e, ['left', 'right', 'center', 'block', 'rounded', 'thumbnail', 'fluid', 'fluidGrow']);
    var props$f = _objectSpread2({}, lazyProps, {
      top: {
        type: Boolean,
        default: false
      },
      bottom: {
        type: Boolean,
        default: false
      },
      start: {
        type: Boolean,
        default: false
      },
      left: {
        // alias of 'start'
        type: Boolean,
        default: false
      },
      end: {
        type: Boolean,
        default: false
      },
      right: {
        // alias of 'end'
        type: Boolean,
        default: false
      }
    }); // @vue/component
  
    var BCardImgLazy = /*#__PURE__*/Vue.extend({
      name: 'BCardImgLazy',
      functional: true,
      props: props$f,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data;
        var baseClass = 'card-img';
  
        if (props.top) {
          baseClass += '-top';
        } else if (props.right || props.end) {
          baseClass += '-right';
        } else if (props.bottom) {
          baseClass += '-bottom';
        } else if (props.left || props.start) {
          baseClass += '-left';
        } // False out the left/center/right props before passing to b-img-lazy
  
  
        var lazyProps = _objectSpread2({}, props, {
          left: false,
          right: false,
          center: false
        });
  
        return h(BImgLazy, a(data, {
          class: [baseClass],
          props: lazyProps
        }));
      }
    });
  
    var props$g = {
      textTag: {
        type: String,
        default: 'p'
      }
    }; // @vue/component
  
    var BCardText = /*#__PURE__*/Vue.extend({
      name: 'BCardText',
      functional: true,
      props: props$g,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.textTag, a(data, {
          staticClass: 'card-text'
        }), children);
      }
    });
  
    var props$h = {
      tag: {
        type: String,
        default: 'div'
      },
      deck: {
        type: Boolean,
        default: false
      },
      columns: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BCardGroup = /*#__PURE__*/Vue.extend({
      name: 'BCardGroup',
      functional: true,
      props: props$h,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          class: props.deck ? 'card-deck' : props.columns ? 'card-columns' : 'card-group'
        }), children);
      }
    });
  
    var CardPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BCard: BCard,
        BCardHeader: BCardHeader,
        BCardBody: BCardBody,
        BCardTitle: BCardTitle,
        BCardSubTitle: BCardSubTitle,
        BCardFooter: BCardFooter,
        BCardImg: BCardImg,
        BCardImgLazy: BCardImgLazy,
        BCardText: BCardText,
        BCardGroup: BCardGroup
      }
    });
  
    var noop = function noop() {};
  
    /**
     * 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} [options={childList: true, subtree: true}] observe options
     * @see http://stackoverflow.com/questions/3219758
     */
  
    var observeDom = function observeDom(el, callback, options)
    /* istanbul ignore next: difficult to test in JSDOM */
    {
      // Handle cases where we might be passed a Vue instance
      el = el ? el.$el || el : null; // Early exit when we have no element
  
      /* istanbul ignore next: difficult to test in JSDOM */
  
      if (!isElement(el)) {
        return null;
      } // Exit and throw a warning when `MutationObserver` isn't available
  
  
      if (warnNoMutationObserverSupport('observeDom')) {
        return null;
      } // Define a new observer
  
  
      var obs = new MutationObs(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 mutation 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; // Detect whether a change happened based on type and 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;
          }
        } // We only call the callback if a change that could affect
        // layout/size truely happened
  
  
        if (changed) {
          callback();
        }
      }); // Have the observer observe foo for changes in children, etc
  
      obs.observe(el, _objectSpread2({
        childList: true,
        subtree: true
      }, options)); // We return a reference to the observer so that `obs.disconnect()`
      // can be called if necessary
      // To reduce overhead when the root element is hidden
  
      return obs;
    };
  
    var EVENT_OPTIONS_PASSIVE = {
      passive: true
    };
    var EVENT_OPTIONS_NO_CAPTURE = {
      passive: true,
      capture: false
    }; // --- Utils ---
    // Normalize event options based on support of passive option
    // Exported only for testing purposes
  
    var parseEventOptions = function parseEventOptions(options) {
      /* istanbul ignore else: can't test in JSDOM, as it supports passive */
      if (hasPassiveEventSupport) {
        return isObject(options) ? options : {
          capture: !!options || false
        };
      } else {
        // Need to translate to actual Boolean value
        return !!(isObject(options) ? options.capture : options);
      }
    }; // Attach an event listener to an element
  
    var eventOn = function eventOn(el, evtName, handler, options) {
      if (el && el.addEventListener) {
        el.addEventListener(evtName, handler, parseEventOptions(options));
      }
    }; // Remove an event listener from an element
  
    var eventOff = function eventOff(el, evtName, handler, options) {
      if (el && el.removeEventListener) {
        el.removeEventListener(evtName, handler, parseEventOptions(options));
      }
    }; // Utility method to add/remove a event listener based on first argument (boolean)
    // It passes all other arguments to the `eventOn()` or `eventOff` method
  
    var eventOnOff = function eventOnOff(on) {
      var method = on ? eventOn : eventOff;
  
      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }
  
      method.apply(void 0, args);
    };
  
    var NAME$a = 'BCarousel'; // 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; // Time for mouse compat events to fire after touch
  
    var TOUCH_EVENT_COMPAT_WAIT = 500; // Number of pixels to consider touch move a swipe
  
    var SWIPE_THRESHOLD = 40; // PointerEvent pointer types
  
    var PointerType = {
      TOUCH: 'touch',
      PEN: 'pen'
    }; // Transition Event names
  
    var TransitionEndEvents = {
      WebkitTransition: 'webkitTransitionEnd',
      MozTransition: 'transitionend',
      OTransition: 'otransitionend oTransitionEnd',
      transition: 'transitionend'
    }; // Return the browser specific transitionEnd event name
  
    var getTransitionEndEvent = function getTransitionEndEvent(el) {
      for (var name in TransitionEndEvents) {
        if (!isUndefined(el.style[name])) {
          return TransitionEndEvents[name];
        }
      } // Fallback
  
      /* istanbul ignore next */
  
  
      return null;
    }; // @vue/component
  
  
    var BCarousel = /*#__PURE__*/Vue.extend({
      name: NAME$a,
      mixins: [idMixin, normalizeSlotMixin],
      provide: function provide() {
        return {
          bvCarousel: this
        };
      },
      model: {
        prop: 'value',
        event: 'input'
      },
      props: {
        labelPrev: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$a, 'labelPrev');
          }
        },
        labelNext: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$a, 'labelNext');
          }
        },
        labelGotoSlide: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$a, 'labelGotoSlide');
          }
        },
        labelIndicators: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$a, 'labelIndicators');
          }
        },
        interval: {
          type: Number,
          default: 5000
        },
        indicators: {
          type: Boolean,
          default: false
        },
        controls: {
          type: Boolean,
          default: false
        },
        noAnimation: {
          // Disable slide/fade animation
          type: Boolean,
          default: false
        },
        fade: {
          // Enable cross-fade animation instead of slide animation
          type: Boolean,
          default: false
        },
        noWrap: {
          // Disable wrapping/looping when start/end is reached
          type: Boolean,
          default: false
        },
        noTouch: {
          // Sniffed by carousel-slide
          type: Boolean,
          default: false
        },
        noHoverPause: {
          // Disable pause on hover
          type: Boolean,
          default: false
        },
        imgWidth: {
          // Sniffed by carousel-slide
          type: [Number, String] // default: undefined
  
        },
        imgHeight: {
          // Sniffed by carousel-slide
          type: [Number, String] // default: undefined
  
        },
        background: {
          type: String // default: undefined
  
        },
        value: {
          type: Number,
          default: 0
        }
      },
      data: function data() {
        return {
          index: this.value || 0,
          isSliding: false,
          transitionEndEvent: null,
          slides: [],
          direction: null,
          isPaused: !(toInteger(this.interval) > 0),
          // Touch event handling values
          touchStartX: 0,
          touchDeltaX: 0
        };
      },
      computed: {
        numSlides: function numSlides() {
          return this.slides.length;
        }
      },
      watch: {
        value: function value(newVal, oldVal) {
          if (newVal !== oldVal) {
            this.setSlide(toInteger(newVal) || 0);
          }
        },
        interval: function interval(newVal, oldVal) {
          if (newVal === oldVal) {
            /* istanbul ignore next */
            return;
          }
  
          if (!newVal) {
            // Pausing slide show
            this.pause(false);
          } else {
            // Restarting or Changing interval
            this.pause(true);
            this.start(false);
          }
        },
        isPaused: function isPaused(newVal, oldVal) {
          if (newVal !== oldVal) {
            this.$emit(newVal ? 'paused' : 'unpaused');
          }
        },
        index: function index(to, from) {
          if (to === from || this.isSliding) {
            /* istanbul ignore next */
            return;
          }
  
          this.doSlide(to, from);
        }
      },
      created: function created() {
        // Create private non-reactive props
        this._intervalId = null;
        this._animationTimeout = null;
        this._touchTimeout = null; // Set initial paused state
  
        this.isPaused = !(toInteger(this.interval) > 0);
      },
      mounted: function mounted() {
        // Cache current browser transitionend event name
        this.transitionEndEvent = getTransitionEndEvent(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']
        });
      },
      beforeDestroy: function beforeDestroy() {
        clearTimeout(this._animationTimeout);
        clearTimeout(this._touchTimeout);
        clearInterval(this._intervalId);
        this._intervalId = null;
        this._animationTimeout = null;
        this._touchTimeout = null;
      },
      methods: {
        // Set slide
        setSlide: function setSlide(slide) {
          var _this = this;
  
          var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  
          // Don't animate when page is not visible
  
          /* istanbul ignore if: difficult to test */
          if (isBrowser && document.visibilityState && document.hidden) {
            return;
          }
  
          var noWrap = this.noWrap;
          var numSlides = this.numSlides; // Make sure we have an integer (you never know!)
  
          slide = Math.floor(slide); // Don't do anything if nothing to slide to
  
          if (numSlides === 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 _this.setSlide(slide, direction);
            });
            return;
          }
  
          this.direction = direction; // Set new slide index
          // Wrap around if necessary (if no-wrap not enabled)
  
          this.index = slide >= numSlides ? noWrap ? numSlides - 1 : 0 : slide < 0 ? noWrap ? 0 : numSlides - 1 : slide; // Ensure the v-model is synched up if no-wrap is enabled
          // and user tried to slide pass either ends
  
          if (noWrap && this.index !== slide && this.index !== this.value) {
            this.$emit('input', this.index);
          }
        },
        // Previous slide
        prev: function prev() {
          this.setSlide(this.index - 1, 'prev');
        },
        // Next slide
        next: function next() {
          this.setSlide(this.index + 1, 'next');
        },
        // Pause auto rotation
        pause: function pause(evt) {
          if (!evt) {
            this.isPaused = true;
          }
  
          if (this._intervalId) {
            clearInterval(this._intervalId);
            this._intervalId = null;
          }
        },
        // Start auto rotate slides
        start: function start(evt) {
          if (!evt) {
            this.isPaused = false;
          }
          /* istanbul ignore next: most likely will never happen, but just in case */
  
  
          if (this._intervalId) {
            clearInterval(this._intervalId);
            this._intervalId = null;
          } // Don't start if no interval, or less than 2 slides
  
  
          if (this.interval && this.numSlides > 1) {
            this._intervalId = setInterval(this.next, Math.max(1000, this.interval));
          }
        },
        // Restart auto rotate slides when focus/hover leaves the carousel
        restart: function restart()
        /* istanbul ignore next: difficult to test */
        {
          if (!this.$el.contains(document.activeElement)) {
            this.start();
          }
        },
        doSlide: function doSlide(to, from) {
          var _this2 = this;
  
          var isCycling = Boolean(this.interval); // Determine sliding direction
  
          var direction = this.calcDirection(this.direction, from, to);
          var overlayClass = direction.overlayClass;
          var dirClass = direction.dirClass; // Determine current and next slides
  
          var currentSlide = this.slides[from];
          var nextSlide = this.slides[to]; // Don't do anything if there aren't any slides to slide to
  
          if (!currentSlide || !nextSlide) {
            /* istanbul ignore next */
            return;
          } // Start animating
  
  
          this.isSliding = true;
  
          if (isCycling) {
            this.pause(false);
          }
  
          this.$emit('sliding-start', to); // Update v-model
  
          this.$emit('input', this.index);
  
          if (this.noAnimation) {
            addClass(nextSlide, 'active');
            removeClass(currentSlide, 'active');
            this.isSliding = false; // Notify ourselves that we're done sliding (slid)
  
            this.$nextTick(function () {
              return _this2.$emit('sliding-end', to);
            });
          } else {
            addClass(nextSlide, overlayClass); // Trigger a reflow of next slide
  
            reflow(nextSlide);
            addClass(currentSlide, dirClass);
            addClass(nextSlide, dirClass); // Transition End handler
  
            var called = false;
            /* istanbul ignore next: difficult to test */
  
            var onceTransEnd = function onceTransEnd() {
              if (called) {
                return;
              }
  
              called = true;
              /* istanbul ignore if: transition events cant be tested in JSDOM */
  
              if (_this2.transitionEndEvent) {
                var events = _this2.transitionEndEvent.split(/\s+/);
  
                events.forEach(function (evt) {
                  return eventOff(currentSlide, evt, onceTransEnd, EVENT_OPTIONS_NO_CAPTURE);
                });
              }
  
              _this2._animationTimeout = null;
              removeClass(nextSlide, dirClass);
              removeClass(nextSlide, overlayClass);
              addClass(nextSlide, 'active');
              removeClass(currentSlide, 'active');
              removeClass(currentSlide, dirClass);
              removeClass(currentSlide, overlayClass);
              setAttr(currentSlide, 'aria-current', 'false');
              setAttr(nextSlide, 'aria-current', 'true');
              setAttr(currentSlide, 'aria-hidden', 'true');
              setAttr(nextSlide, 'aria-hidden', 'false');
              _this2.isSliding = false;
              _this2.direction = null; // Notify ourselves that we're done sliding (slid)
  
              _this2.$nextTick(function () {
                return _this2.$emit('sliding-end', to);
              });
            }; // Set up transitionend handler
  
            /* istanbul ignore if: transition events cant be tested in JSDOM */
  
  
            if (this.transitionEndEvent) {
              var events = this.transitionEndEvent.split(/\s+/);
              events.forEach(function (event) {
                return eventOn(currentSlide, event, onceTransEnd, EVENT_OPTIONS_NO_CAPTURE);
              });
            } // Fallback to setTimeout()
  
  
            this._animationTimeout = setTimeout(onceTransEnd, TRANS_DURATION);
          }
  
          if (isCycling) {
            this.start(false);
          }
        },
        // Update slide list
        updateSlides: function updateSlides() {
          this.pause(true); // 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');
              setAttr(slide, 'aria-current', 'true');
            } else {
              removeClass(slide, 'active');
              setAttr(slide, 'aria-current', 'false');
            }
  
            setAttr(slide, 'aria-posinset', String(n));
            setAttr(slide, 'aria-setsize', String(numSlides));
          }); // Set slide as active
  
          this.setSlide(index);
          this.start(this.isPaused);
        },
        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];
        },
        handleClick: function handleClick(evt, fn) {
          var keyCode = evt.keyCode;
  
          if (evt.type === 'click' || keyCode === KEY_CODES.SPACE || keyCode === KEY_CODES.ENTER) {
            evt.preventDefault();
            evt.stopPropagation();
            fn();
          }
        },
        handleSwipe: function handleSwipe()
        /* istanbul ignore next: JSDOM doesn't support touch events */
        {
          var absDeltaX = Math.abs(this.touchDeltaX);
  
          if (absDeltaX <= SWIPE_THRESHOLD) {
            return;
          }
  
          var direction = absDeltaX / this.touchDeltaX; // Reset touch delta X
          // https://github.com/twbs/bootstrap/pull/28558
  
          this.touchDeltaX = 0;
  
          if (direction > 0) {
            // Swipe left
            this.prev();
          } else if (direction < 0) {
            // Swipe right
            this.next();
          }
        },
        touchStart: function touchStart(evt)
        /* istanbul ignore next: JSDOM doesn't support touch events */
        {
          if (hasPointerEventSupport && PointerType[evt.pointerType.toUpperCase()]) {
            this.touchStartX = evt.clientX;
          } else if (!hasPointerEventSupport) {
            this.touchStartX = evt.touches[0].clientX;
          }
        },
        touchMove: function touchMove(evt)
        /* istanbul ignore next: JSDOM doesn't support touch events */
        {
          // Ensure swiping with one touch and not pinching
          if (evt.touches && evt.touches.length > 1) {
            this.touchDeltaX = 0;
          } else {
            this.touchDeltaX = evt.touches[0].clientX - this.touchStartX;
          }
        },
        touchEnd: function touchEnd(evt)
        /* istanbul ignore next: JSDOM doesn't support touch events */
        {
          if (hasPointerEventSupport && PointerType[evt.pointerType.toUpperCase()]) {
            this.touchDeltaX = evt.clientX - this.touchStartX;
          }
  
          this.handleSwipe(); // If it's a touch-enabled device, mouseenter/leave are fired as
          // part of the mouse compatibility events on first tap - the carousel
          // would stop cycling until user tapped out of it;
          // here, we listen for touchend, explicitly pause the carousel
          // (as if it's the second time we tap on it, mouseenter compat event
          // is NOT fired) and after a timeout (to allow for mouse compatibility
          // events to fire) we explicitly restart cycling
  
          this.pause(false);
  
          if (this._touchTimeout) {
            clearTimeout(this._touchTimeout);
          }
  
          this._touchTimeout = setTimeout(this.start, TOUCH_EVENT_COMPAT_WAIT + Math.max(1000, this.interval));
        }
      },
      render: function render(h) {
        var _this3 = this;
  
        // Wrapper for slides
        var inner = h('div', {
          ref: 'inner',
          class: ['carousel-inner'],
          attrs: {
            id: this.safeId('__BV_inner_'),
            role: 'list'
          }
        }, [this.normalizeSlot('default')]); // Prev and next controls
  
        var controls = h();
  
        if (this.controls) {
          var prevHandler = function prevHandler(evt) {
            /* istanbul ignore next */
            if (!_this3.isSliding) {
              _this3.handleClick(evt, _this3.prev);
            } else {
              evt.preventDefault();
            }
          };
  
          var nextHandler = function nextHandler(evt) {
            /* istanbul ignore next */
            if (!_this3.isSliding) {
              _this3.handleClick(evt, _this3.next);
            } else {
              evt.preventDefault();
            }
          };
  
          controls = [h('a', {
            class: ['carousel-control-prev'],
            attrs: {
              href: '#',
              role: 'button',
              'aria-controls': this.safeId('__BV_inner_'),
              'aria-disabled': this.isSliding ? 'true' : null
            },
            on: {
              click: prevHandler,
              keydown: prevHandler
            }
          }, [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_'),
              'aria-disabled': this.isSliding ? 'true' : null
            },
            on: {
              click: nextHandler,
              keydown: nextHandler
            }
          }, [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_".concat(n),
            class: {
              active: n === _this3.index
            },
            attrs: {
              role: 'button',
              id: _this3.safeId("__BV_indicator_".concat(n + 1, "_")),
              tabindex: _this3.indicators ? '0' : '-1',
              'aria-current': n === _this3.index ? 'true' : 'false',
              'aria-label': "".concat(_this3.labelGotoSlide, " ").concat(n + 1),
              'aria-describedby': _this3.slides[n].id || null,
              'aria-controls': _this3.safeId('__BV_inner_')
            },
            on: {
              click: function click(evt) {
                _this3.handleClick(evt, function () {
                  _this3.setSlide(n);
                });
              },
              keydown: function keydown(evt) {
                _this3.handleClick(evt, function () {
                  _this3.setSlide(n);
                });
              }
            }
          });
        }));
        var on = {
          mouseenter: this.noHoverPause ? noop : this.pause,
          mouseleave: this.noHoverPause ? noop : this.restart,
          focusin: this.pause,
          focusout: this.restart,
          keydown: function keydown(evt) {
            if (/input|textarea/i.test(evt.target.tagName)) {
              /* istanbul ignore next */
              return;
            }
  
            var keyCode = evt.keyCode;
  
            if (keyCode === KEY_CODES.LEFT || keyCode === KEY_CODES.RIGHT) {
              evt.preventDefault();
              evt.stopPropagation();
  
              _this3[keyCode === KEY_CODES.LEFT ? 'prev' : 'next']();
            }
          }
        }; // Touch support event handlers for environment
  
        if (!this.noTouch && hasTouchSupport) {
          // Attach appropriate listeners (prepend event name with '&' for passive mode)
  
          /* istanbul ignore next: JSDOM doesn't support touch events */
          if (hasPointerEventSupport) {
            on['&pointerdown'] = this.touchStart;
            on['&pointerup'] = this.touchEnd;
          } else {
            on['&touchstart'] = this.touchStart;
            on['&touchmove'] = this.touchMove;
            on['&touchend'] = this.touchEnd;
          }
        } // Return the carousel
  
  
        return h('div', {
          staticClass: 'carousel',
          class: {
            slide: !this.noAnimation,
            'carousel-fade': !this.noAnimation && this.fade,
            'pointer-event': !this.noTouch && hasTouchSupport && hasPointerEventSupport
          },
          style: {
            background: this.background
          },
          attrs: {
            role: 'region',
            id: this.safeId(),
            'aria-busy': this.isSliding ? 'true' : 'false'
          },
          on: on
        }, [inner, controls, indicators]);
      }
    });
  
    var props$i = {
      imgSrc: {
        type: String // default: undefined
  
      },
      imgAlt: {
        type: String // default: undefined
  
      },
      imgWidth: {
        type: [Number, String] // default: undefined
  
      },
      imgHeight: {
        type: [Number, String] // default: undefined
  
      },
      imgBlank: {
        type: Boolean,
        default: false
      },
      imgBlankColor: {
        type: String,
        default: 'transparent'
      },
      contentVisibleUp: {
        type: String
      },
      contentTag: {
        type: String,
        default: 'div'
      },
      caption: {
        type: String
      },
      captionHtml: {
        type: String
      },
      captionTag: {
        type: String,
        default: 'h3'
      },
      text: {
        type: String
      },
      textHtml: {
        type: String
      },
      textTag: {
        type: String,
        default: 'p'
      },
      background: {
        type: String
      }
    }; // @vue/component
  
    var BCarouselSlide = /*#__PURE__*/Vue.extend({
      name: 'BCarouselSlide',
      mixins: [idMixin, normalizeSlotMixin],
      inject: {
        bvCarousel: {
          default: function _default() {
            return {
              // Explicitly disable touch if not a child of carousel
              noTouch: true
            };
          }
        }
      },
      props: props$i,
      computed: {
        contentClasses: function contentClasses() {
          return [this.contentVisibleUp ? 'd-none' : '', this.contentVisibleUp ? "d-".concat(this.contentVisibleUp, "-block") : ''];
        },
        computedWidth: function computedWidth() {
          // Use local width, or try parent width
          return this.imgWidth || this.bvCarousel.imgWidth || null;
        },
        computedHeight: function computedHeight() {
          // Use local height, or try parent height
          return this.imgHeight || this.bvCarousel.imgHeight || null;
        }
      },
      render: function render(h) {
        var noDrag = !this.bvCarousel.noTouch && hasTouchSupport;
        var img = this.normalizeSlot('img');
  
        if (!img && (this.imgSrc || this.imgBlank)) {
          img = h(BImg, {
            props: {
              fluidGrow: true,
              block: true,
              src: this.imgSrc,
              blank: this.imgBlank,
              blankColor: this.imgBlankColor,
              width: this.computedWidth,
              height: this.computedHeight,
              alt: this.imgAlt
            },
            // Touch support event handler
            on: noDrag ? {
              dragstart: function dragstart(e) {
                /* istanbul ignore next: difficult to test in JSDOM */
                e.preventDefault();
              }
            } : {}
          });
        }
  
        if (!img) {
          img = h();
        }
  
        var content = h();
        var contentChildren = [this.caption || this.captionHtml ? h(this.captionTag, {
          domProps: htmlOrText(this.captionHtml, this.caption)
        }) : false, this.text || this.textHtml ? h(this.textTag, {
          domProps: htmlOrText(this.textHtml, this.text)
        }) : false, this.normalizeSlot('default') || false];
  
        if (contentChildren.some(Boolean)) {
          content = h(this.contentTag, {
            staticClass: 'carousel-caption',
            class: this.contentClasses
          }, contentChildren.map(function (i) {
            return i || h();
          }));
        }
  
        return h('div', {
          staticClass: 'carousel-item',
          style: {
            background: this.background || this.bvCarousel.background || null
          },
          attrs: {
            id: this.safeId(),
            role: 'listitem'
          }
        }, [img, content]);
      }
    });
  
    var CarouselPlugin =
    /*#__PURE*/
    pluginFactory({
      components: {
        BCarousel: BCarousel,
        BCarouselSlide: BCarouselSlide
      }
    });
  
    // Generic collapse transion helper component
  
    var onEnter = function onEnter(el) {
      el.style.height = 0; // Animaton frame delay neeeded for `appear` to work
  
      requestAF(function () {
        reflow(el);
        el.style.height = "".concat(el.scrollHeight, "px");
      });
    };
  
    var onAfterEnter = function onAfterEnter(el) {
      el.style.height = null;
    };
  
    var onLeave = function onLeave(el) {
      el.style.height = 'auto';
      el.style.display = 'block';
      el.style.height = "".concat(getBCR(el).height, "px");
      reflow(el);
      el.style.height = 0;
    };
  
    var onAfterLeave = function onAfterLeave(el) {
      el.style.height = null;
    }; // Default transition props
    // `appear` will use the enter classes
  
  
    var TRANSITION_PROPS = {
      css: true,
      enterClass: '',
      enterActiveClass: 'collapsing',
      enterToClass: 'collapse show',
      leaveClass: 'collapse show',
      leaveActiveClass: 'collapsing',
      leaveToClass: 'collapse'
    }; // Default transition handlers
    // `appear` will use the enter handlers
  
    var TRANSITION_HANDLERS = {
      enter: onEnter,
      afterEnter: onAfterEnter,
      leave: onLeave,
      afterLeave: onAfterLeave
    }; // @vue/component
  
    var BVCollapse = /*#__PURE__*/Vue.extend({
      name: 'BVCollapse',
      functional: true,
      props: {
        appear: {
          // If `true` (and `visible` is `true` on mount), animate initially visible
          type: Boolean,
          default: false
        }
      },
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h('transition', // We merge in the `appear` prop last
        a(data, {
          props: TRANSITION_PROPS,
          on: TRANSITION_HANDLERS
        }, {
          props: props
        }), // Note: `<tranition>` supports a single root element only
        children);
      }
    });
  
    /**
     * Issue #569: collapse::toggle::state triggered too many times
     * @link https://github.com/bootstrap-vue/bootstrap-vue/issues/569
     */
    // @vue/component
    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.
         *
         * When registering a $root listener, it also registers a listener on
         * the component's `beforeDestroy` hook to automatically remove the
         * event listener from the $root instance.
         *
         * @param {string} event
         * @param {function} callback
         * @chainable
         */
        listenOnRoot: function listenOnRoot(event, callback) {
          var _this = this;
  
          this.$root.$on(event, callback);
          this.$on('hook:beforeDestroy', function () {
            _this.$root.$off(event, callback);
          }); // Return this for easy chaining
  
          return this;
        },
  
        /**
         * Safely register a $once event listener 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.
         *
         * When registering a $root listener, it also registers a listener on
         * the component's `beforeDestroy` hook to automatically remove the
         * event listener from the $root instance.
         *
         * @param {string} event
         * @param {function} callback
         * @chainable
         */
        listenOnRootOnce: function listenOnRootOnce(event, callback) {
          var _this2 = this;
  
          this.$root.$once(event, callback);
          this.$on('hook:beforeDestroy', function () {
            _this2.$root.$off(event, callback);
          }); // Return this for easy chaining
  
          return this;
        },
  
        /**
         * Convenience method for calling vm.$emit on vm.$root.
         * @param {string} event
         * @param {*} args
         * @chainable
         */
        emitOnRoot: function emitOnRoot(event) {
          var _this$$root;
  
          for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
            args[_key - 1] = arguments[_key];
          }
  
          (_this$$root = this.$root).$emit.apply(_this$$root, [event].concat(args)); // Return this for easy chaining
  
  
          return this;
        }
      }
    };
  
    var EVENT_STATE = 'bv::collapse::state';
    var EVENT_ACCORDION = 'bv::collapse::accordion'; // Private event we emit on `$root` to ensure the toggle state is
    // always synced. It gets emitted even if the state has not changed!
    // This event is NOT to be documented as people should not be using it
  
    var EVENT_STATE_SYNC = 'bv::collapse::sync::state'; // Events we listen to on `$root`
  
    var EVENT_TOGGLE = 'bv::toggle::collapse';
    var EVENT_STATE_REQUEST = 'bv::request::collapse::state'; // @vue/component
  
    var BCollapse = /*#__PURE__*/Vue.extend({
      name: 'BCollapse',
      mixins: [idMixin, listenOnRootMixin, normalizeSlotMixin],
      model: {
        prop: 'visible',
        event: 'input'
      },
      props: {
        isNav: {
          type: Boolean,
          default: false
        },
        accordion: {
          type: String,
          default: null
        },
        visible: {
          type: Boolean,
          default: false
        },
        tag: {
          type: String,
          default: 'div'
        },
        appear: {
          // If `true` (and `visible` is `true` on mount), animate initially visible
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          show: this.visible,
          transitioning: false
        };
      },
      computed: {
        classObject: function classObject() {
          return {
            'navbar-collapse': this.isNav,
            collapse: !this.transitioning,
            show: this.show && !this.transitioning
          };
        }
      },
      watch: {
        visible: function visible(newVal) {
          if (newVal !== this.show) {
            this.show = newVal;
          }
        },
        show: function show(newVal, oldVal) {
          if (newVal !== oldVal) {
            this.emitState();
          }
        }
      },
      created: function created() {
        this.show = this.visible;
      },
      mounted: function mounted() {
        var _this = this;
  
        this.show = this.visible; // Listen for toggle events to open/close us
  
        this.listenOnRoot(EVENT_TOGGLE, this.handleToggleEvt); // Listen to other collapses for accordion events
  
        this.listenOnRoot(EVENT_ACCORDION, this.handleAccordionEvt);
  
        if (this.isNav) {
          // Set up handlers
          this.setWindowEvents(true);
          this.handleResize();
        }
  
        this.$nextTick(function () {
          _this.emitState();
        }); // Listen for "Sync state" requests from `v-b-toggle`
  
        this.listenOnRoot(EVENT_STATE_REQUEST, function (id) {
          if (id === _this.safeId()) {
            _this.$nextTick(_this.emitSync);
          }
        });
      },
      updated: function updated() {
        // Emit a private event every time this component updates to ensure
        // the toggle button is in sync with the collapse's state
        // It is emitted regardless if the visible state changes
        this.emitSync();
      },
      deactivated: function deactivated()
      /* istanbul ignore next */
      {
        if (this.isNav) {
          this.setWindowEvents(false);
        }
      },
      activated: function activated()
      /* istanbul ignore next */
      {
        if (this.isNav) {
          this.setWindowEvents(true);
        }
  
        this.emitSync();
      },
      beforeDestroy: function beforeDestroy() {
        // Trigger state emit if needed
        this.show = false;
  
        if (this.isNav && isBrowser) {
          this.setWindowEvents(false);
        }
      },
      methods: {
        setWindowEvents: function setWindowEvents(on) {
          eventOnOff(on, window, 'resize', this.handleResize, EVENT_OPTIONS_NO_CAPTURE);
          eventOnOff(on, window, 'orientationchange', this.handleResize, EVENT_OPTIONS_NO_CAPTURE);
        },
        toggle: function toggle() {
          this.show = !this.show;
        },
        onEnter: function onEnter() {
          this.transitioning = true; // This should be moved out so we can add cancellable events
  
          this.$emit('show');
        },
        onAfterEnter: function onAfterEnter() {
          this.transitioning = false;
          this.$emit('shown');
        },
        onLeave: function onLeave() {
          this.transitioning = true; // This should be moved out so we can add cancellable events
  
          this.$emit('hide');
        },
        onAfterLeave: function onAfterLeave() {
          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.safeId(), this.show);
  
          if (this.accordion && this.show) {
            // Tell the other collapses in this accordion to close
            this.$root.$emit(EVENT_ACCORDION, this.safeId(), this.accordion);
          }
        },
        emitSync: function emitSync() {
          // Emit a private event every time this component updates to ensure
          // the toggle button is in sync with the collapse's state
          // It is emitted regardless if the visible state changes
          this.$root.$emit(EVENT_STATE_SYNC, this.safeId(), this.show);
        },
        checkDisplayBlock: function checkDisplayBlock() {
          // Check to see if the collapse has `display: block !important` set
          // We can't set `display: none` directly on `this.$el`, as it would
          // trigger a new transition to start (or cancel a current one)
          var restore = hasClass(this.$el, 'show');
          removeClass(this.$el, 'show');
          var isBlock = getCS(this.$el).display === 'block';
  
          if (restore) {
            addClass(this.$el, 'show');
          }
  
          return isBlock;
        },
        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 || getCS(this.$el).display !== 'block') {
            /* istanbul ignore next: can't test getComputedStyle in JSDOM */
            return;
          }
  
          if (matches(el, '.nav-link,.dropdown-item') || closest('.nav-link,.dropdown-item', el)) {
            if (!this.checkDisplayBlock()) {
              // Only close the collapse if it is not forced to be `display: block !important`
              this.show = false;
            }
          }
        },
        handleToggleEvt: function handleToggleEvt(target) {
          if (target !== this.safeId()) {
            return;
          }
  
          this.toggle();
        },
        handleAccordionEvt: function handleAccordionEvt(openedId, accordion) {
          if (!this.accordion || accordion !== this.accordion) {
            return;
          }
  
          if (openedId === this.safeId()) {
            // 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 = getCS(this.$el).display === 'block';
        }
      },
      render: function render(h) {
        var _this2 = this;
  
        var scope = {
          visible: this.show,
          close: function close() {
            return _this2.show = false;
          }
        };
        var content = h(this.tag, {
          class: this.classObject,
          directives: [{
            name: 'show',
            value: this.show
          }],
          attrs: {
            id: this.safeId()
          },
          on: {
            click: this.clickHandler
          }
        }, [this.normalizeSlot('default', scope)]);
        return h(BVCollapse, {
          props: {
            appear: this.appear
          },
          on: {
            enter: this.onEnter,
            afterEnter: this.onAfterEnter,
            leave: this.onLeave,
            afterLeave: this.onAfterLeave
          }
        }, [content]);
      }
    });
  
    var allListenTypes = {
      hover: true,
      click: true,
      focus: true
    };
    var BVBoundListeners = '__BV_boundEventListeners__';
  
    var getTargets = function getTargets(binding) {
      var targets = keys(binding.modifiers || {}).filter(function (t) {
        return !allListenTypes[t];
      });
  
      if (binding.value) {
        targets.push(binding.value);
      }
  
      return targets;
    };
  
    var bindTargets = function bindTargets(vnode, binding, listenTypes, fn) {
      var targets = getTargets(binding);
  
      var listener = function listener() {
        fn({
          targets: targets,
          vnode: vnode
        });
      };
  
      keys(allListenTypes).forEach(function (type) {
        if (listenTypes[type] || binding.modifiers[type]) {
          eventOn(vnode.elm, 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 eventOff(vnode.elm, type, listener);
            });
            delete vnode.elm[BVBoundListeners][type];
          }
        }
      });
    };
  
    var listenTypes = {
      click: true
    }; // Property key for handler storage
  
    var BV_TOGGLE = '__BV_toggle__';
    var BV_TOGGLE_STATE = '__BV_toggle_STATE__';
    var BV_TOGGLE_CONTROLS = '__BV_toggle_CONTROLS__';
    var BV_TOGGLE_TARGETS = '__BV_toggle_TARGETS__'; // Emitted control event for collapse (emitted to collapse)
  
    var EVENT_TOGGLE$1 = 'bv::toggle::collapse'; // Listen to event for toggle state update (emitted by collapse)
  
    var EVENT_STATE$1 = 'bv::collapse::state'; // Private event emitted on $root to ensure the toggle state is always synced.
    // Gets emitted even if the state of b-collapse has not changed.
    // This event is NOT to be documented as people should not be using it.
  
    var EVENT_STATE_SYNC$1 = 'bv::collapse::sync::state'; // Private event we send to collapse to request state update sync event
  
    var EVENT_STATE_REQUEST$1 = 'bv::request::collapse::state'; // Reset and remove a property from the provided element
  
    var resetProp = function resetProp(el, prop) {
      el[prop] = null;
      delete el[prop];
    }; // Handle targets update
  
  
    var handleTargets = function handleTargets(_ref) {
      var targets = _ref.targets,
          vnode = _ref.vnode;
      targets.forEach(function (target) {
        vnode.context.$root.$emit(EVENT_TOGGLE$1, target);
      });
    }; // Handle directive updates
  
    /* istanbul ignore next: not easy to test */
  
  
    var handleUpdate = function handleUpdate(el, binding, vnode) {
      if (!isBrowser) {
        return;
      }
  
      if (!looseEqual(getTargets(binding), el[BV_TOGGLE_TARGETS])) {
        // Targets have changed, so update accordingly
        unbindTargets(vnode, binding, listenTypes);
        var targets = bindTargets(vnode, binding, listenTypes, handleTargets); // Update targets array to element
  
        el[BV_TOGGLE_TARGETS] = targets; // Add aria attributes to element
  
        el[BV_TOGGLE_CONTROLS] = targets.join(' '); // ensure aria-controls is up to date
  
        setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS]); // Request a state update from targets so that we can ensure
        // expanded state is correct
  
        targets.forEach(function (target) {
          vnode.context.$root.$emit(EVENT_STATE_REQUEST$1, target);
        });
      } // Ensure the collapse class and aria-* attributes persist
      // after element is updated (either by parent re-rendering
      // or changes to this element or its contents
  
  
      if (el[BV_TOGGLE_STATE] === true) {
        addClass(el, 'collapsed');
        setAttr(el, 'aria-expanded', 'true');
      } else if (el[BV_TOGGLE_STATE] === false) {
        removeClass(el, 'collapsed');
        setAttr(el, 'aria-expanded', 'false');
      }
  
      setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS]);
    };
    /*
     * Export our directive
     */
  
  
    var VBToggle = {
      bind: function bind(el, binding, vnode) {
        var targets = bindTargets(vnode, binding, listenTypes, handleTargets);
  
        if (isBrowser && vnode.context && targets.length > 0) {
          // Add targets array to element
          el[BV_TOGGLE_TARGETS] = targets; // Add aria attributes to element
  
          el[BV_TOGGLE_CONTROLS] = targets.join(' '); // State is initially collapsed until we receive a state event
  
          el[BV_TOGGLE_STATE] = false;
          setAttr(el, 'aria-controls', el[BV_TOGGLE_CONTROLS]);
          setAttr(el, 'aria-expanded', 'false'); // If element is not a button, we add `role="button"` for accessibility
  
          if (el.tagName !== 'BUTTON' && !hasAttr(el, 'role')) {
            setAttr(el, 'role', 'button');
          } // Toggle state handler
  
  
          var toggleDirectiveHandler = function toggleDirectiveHandler(id, state) {
            var targets = el[BV_TOGGLE_TARGETS] || [];
  
            if (targets.indexOf(id) !== -1) {
              // Set aria-expanded state
              setAttr(el, 'aria-expanded', state ? 'true' : 'false'); // Set/Clear 'collapsed' class state
  
              el[BV_TOGGLE_STATE] = state;
  
              if (state) {
                removeClass(el, 'collapsed');
              } else {
                addClass(el, 'collapsed');
              }
            }
          }; // Store the toggle handler on the element
  
  
          el[BV_TOGGLE] = toggleDirectiveHandler; // Listen for toggle state changes (public)
  
          vnode.context.$root.$on(EVENT_STATE$1, el[BV_TOGGLE]); // Listen for toggle state sync (private)
  
          vnode.context.$root.$on(EVENT_STATE_SYNC$1, el[BV_TOGGLE]);
        }
      },
      componentUpdated: handleUpdate,
      updated: handleUpdate,
      unbind: function unbind(el, binding, vnode)
      /* istanbul ignore next */
      {
        unbindTargets(vnode, binding, listenTypes); // Remove our $root listener
  
        if (el[BV_TOGGLE]) {
          vnode.context.$root.$off(EVENT_STATE$1, el[BV_TOGGLE]);
          vnode.context.$root.$off(EVENT_STATE_SYNC$1, el[BV_TOGGLE]);
        } // Reset custom  props
  
  
        resetProp(el, BV_TOGGLE);
        resetProp(el, BV_TOGGLE_STATE);
        resetProp(el, BV_TOGGLE_CONTROLS);
        resetProp(el, BV_TOGGLE_TARGETS); // Reset classes/attrs
  
        removeClass(el, 'collapsed');
        removeAttr(el, 'aria-expanded');
        removeAttr(el, 'aria-controls');
        removeAttr(el, 'role');
      }
    };
  
    var CollapsePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BCollapse: BCollapse
      },
      directives: {
        VBToggle: VBToggle
      }
    });
  
    /**!
     * @fileOverview Kickass library to create and place poppers near their reference elements.
     * @version 1.16.1
     * @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$1 = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined';
  
    var timeoutDuration = function () {
      var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
      for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
        if (isBrowser$1 && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
          return 1;
        }
      }
      return 0;
    }();
  
    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$1 && 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$1(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 window = element.ownerDocument.defaultView;
      var css = window.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));
    }
  
    /**
     * Returns the reference node of the reference object, or the reference object itself.
     * @method
     * @memberof Popper.Utils
     * @param {Element|Object} reference - the reference element (the popper will be relative to this)
     * @returns {Element} parent
     */
    function getReferenceNode(reference) {
      return reference && reference.referenceNode ? reference.referenceNode : reference;
    }
  
    var isIE11 = isBrowser$1 && !!(window.MSInputMethodContext && document.documentMode);
    var isIE10 = isBrowser$1 && /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$1(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$1(10) ? document.body : null;
  
      // NOTE: 1 DOM access here
      var offsetParent = element.offsetParent || null;
      // 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 TH, TD or TABLE in case
      // no offsetParent is present, I hate this job...
      if (['TH', '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']) + parseFloat(styles['border' + sideB + 'Width']);
    }
  
    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$1(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
    }
  
    function getWindowSizes(document) {
      var body = document.body;
      var html = document.documentElement;
      var computedStyle = isIE$1(10) && getComputedStyle(html);
  
      return {
        height: getSize('Height', body, html, computedStyle),
        width: getSize('Width', body, html, computedStyle)
      };
    }
  
    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$1 = 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 _extends = 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({}, 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$1(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(element.ownerDocument) : {};
      var width = sizes.width || element.clientWidth || result.width;
      var height = sizes.height || element.clientHeight || result.height;
  
      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$1(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);
      var borderLeftWidth = parseFloat(styles.borderLeftWidth);
  
      // In cases where the parent is fixed, we must ignore negative scroll in offset calc
      if (fixedPosition && isHTML) {
        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);
        var marginLeft = parseFloat(styles.marginLeft);
  
        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;
      }
      var parentNode = getParentNode(element);
      if (!parentNode) {
        return false;
      }
      return isFixed(parentNode);
    }
  
    /**
     * 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$1()) {
        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, getReferenceNode(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(popper.ownerDocument),
              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
      padding = padding || 0;
      var isPaddingNumber = typeof padding === 'number';
      boundaries.left += isPaddingNumber ? padding : padding.left || 0;
      boundaries.top += isPaddingNumber ? padding : padding.top || 0;
      boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
      boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
  
      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({
          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, getReferenceNode(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 window = element.ownerDocument.defaultView;
      var styles = window.getComputedStyle(element);
      var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
      var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
      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$1(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.<br />
     * 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;
    }
  
    /**
     * Destroys the popper.
     * @method
     * @memberof Popper
     */
    function destroy$1() {
      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 explicitly 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 Popper.Utils
     * @argument {Object} data - The data object generated by `update` method
     * @argument {Boolean} shouldRound - If the offsets should be rounded at all
     * @returns {Object} The popper's position offsets rounded
     *
     * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
     * good as it can be within reason.
     * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
     *
     * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
     * as well on High DPI screens).
     *
     * Firefox prefers no rounding for positioning and does not have blurriness on
     * high DPI screens.
     *
     * Only horizontal placement and left/right values need to be considered.
     */
    function getRoundedOffsets(data, shouldRound) {
      var _data$offsets = data.offsets,
          popper = _data$offsets.popper,
          reference = _data$offsets.reference;
      var round = Math.round,
          floor = Math.floor;
  
      var noRound = function noRound(v) {
        return v;
      };
  
      var referenceWidth = round(reference.width);
      var popperWidth = round(popper.width);
  
      var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
      var isVariation = data.placement.indexOf('-') !== -1;
      var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
      var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
  
      var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
      var verticalToInteger = !shouldRound ? noRound : round;
  
      return {
        left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
        top: verticalToInteger(popper.top),
        bottom: verticalToInteger(popper.bottom),
        right: horizontalToInteger(popper.right)
      };
    }
  
    var isFirefox = isBrowser$1 && /Firefox/i.test(navigator.userAgent);
  
    /**
     * @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
      };
  
      var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
  
      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') {
        // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
        // and not the bottom of the html element
        if (offsetParent.nodeName === 'HTML') {
          top = -offsetParent.clientHeight + offsets.bottom;
        } else {
          top = -offsetParentRect.height + offsets.bottom;
        }
      } else {
        top = offsets.top;
      }
      if (sideB === 'right') {
        if (offsetParent.nodeName === 'HTML') {
          left = -offsetParent.clientWidth + offsets.right;
        } else {
          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({}, attributes, data.attributes);
      data.styles = _extends({}, styles, data.styles);
      data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
  
      return data;
    }
  
    /**
     * Helper used to know if the given modifier depends from another one.<br />
     * 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 conjunction
      //
  
      // 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]);
      var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width']);
      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$1(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty$1(_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.<br />
     * 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.<br />
     * 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-end` (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;
  
        // flips variation if reference element overflows boundaries
        var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
  
        // flips variation if popper content overflows boundaries
        var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
  
        var flippedVariation = flippedVariationByRef || flippedVariationByContent;
  
        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({}, 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$1({}, 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$1({}, mainSide, value);
        }
      };
  
      order.forEach(function (placement) {
        var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
        popper = _extends({}, 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$1({}, side, reference[side]),
          end: defineProperty$1({}, side, reference[side] + reference[measurement] - popper[measurement])
        };
  
        data.offsets.popper = _extends({}, 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.<br />
     * 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.<br />
     * 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.<br />
       * It will read the variation of the `placement` property.<br />
       * 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 unit-less, 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.<br />
       * 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.<br />
       * The latter is a deprecated method because it leads to confusion and will be
       * removed in v2.<br />
       * 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.
       * > You can read more on this at 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.
       *
       * A scenario exists where the reference itself is not within the boundaries.<br />
       * We can say it has "escaped the boundaries" — or just "escaped".<br />
       * 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 always has 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 each other
       * without leaving any gap between the two. Especially useful when the arrow is
       * enabled and you want to ensure that it points 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 conjunction 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',
        /**
         * @prop {Boolean} flipVariations=false
         * The popper will switch placement variation between `-start` and `-end` when
         * the reference element overlaps its boundaries.
         *
         * The original placement should have a set variation.
         */
        flipVariations: false,
        /**
         * @prop {Boolean} flipVariationsByContent=false
         * The popper will switch placement variation between `-start` and `-end` when
         * the popper element overlaps its reference boundaries.
         *
         * The original placement should have a set variation.
         */
        flipVariationsByContent: false
      },
  
      /**
       * 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 your 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 information used by Popper.js.
     * This object is 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.<br />
     * These can be overridden using the `options` argument of Popper.js.<br />
     * To override an option, simply pass an object with the same
     * structure of the `options` object, as the 3rd argument. For 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.<br />
       * By default, it is set to no-op.<br />
       * 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.<br />
       * By default, it is set to no-op.<br />
       * 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 () {
      /**
       * Creates a new Popper.js instance.
       * @class Popper
       * @param {Element|referenceObject} reference - The reference element used to position the popper
       * @param {Element} popper - The HTML / XML element used as the 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(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({}, 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({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
          _this.options.modifiers[name] = _extends({}, 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({
            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$1(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(Popper, [{
        key: 'update',
        value: function update$$1() {
          return update.call(this);
        }
      }, {
        key: 'destroy',
        value: function destroy$$1() {
          return destroy$1.call(this);
        }
      }, {
        key: 'enableEventListeners',
        value: function enableEventListeners$$1() {
          return enableEventListeners.call(this);
        }
      }, {
        key: 'disableEventListeners',
        value: function disableEventListeners$$1() {
          return disableEventListeners.call(this);
        }
  
        /**
         * Schedules 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.<br />
     * 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 BvEvent = /*#__PURE__*/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) {
          /* istanbul ignore next */
          throw new TypeError("Failed to construct '".concat(this.constructor.name, "'. 1 argument required, ").concat(arguments.length, " given."));
        } // Merge defaults first, the eventInit, and the type last
        // so it can't be overwritten
  
  
        assign(this, BvEvent.Defaults, this.constructor.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(),
          componentId: 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(this, 'defaultPrevented', {
          enumerable: true,
          get: function get() {
            return defaultPrevented;
          }
        });
      }
  
      _createClass(BvEvent, null, [{
        key: "Defaults",
        get: function get() {
          return {
            type: '',
            cancelable: true,
            nativeEvent: null,
            target: null,
            relatedTarget: null,
            vueTarget: null,
            componentId: null
          };
        }
      }]);
  
      return BvEvent;
    }(); // Named Exports
  
    var clickOutMixin = {
      data: function data() {
        return {
          listenForClickOut: false
        };
      },
      watch: {
        listenForClickOut: function listenForClickOut(newValue, oldValue) {
          if (newValue !== oldValue) {
            eventOff(this.clickOutElement, this.clickOutEventName, this._clickOutHandler, EVENT_OPTIONS_NO_CAPTURE);
  
            if (newValue) {
              eventOn(this.clickOutElement, this.clickOutEventName, this._clickOutHandler, EVENT_OPTIONS_NO_CAPTURE);
            }
          }
        }
      },
      beforeCreate: function beforeCreate() {
        // Declare non-reactive properties
        this.clickOutElement = null;
        this.clickOutEventName = null;
      },
      mounted: function mounted() {
        if (!this.clickOutElement) {
          this.clickOutElement = document;
        }
  
        if (!this.clickOutEventName) {
          this.clickOutEventName = 'click';
        }
  
        if (this.listenForClickOut) {
          eventOn(this.clickOutElement, this.clickOutEventName, this._clickOutHandler, EVENT_OPTIONS_NO_CAPTURE);
        }
      },
      beforeDestroy: function beforeDestroy()
      /* istanbul ignore next */
      {
        eventOff(this.clickOutElement, this.clickOutEventName, this._clickOutHandler, EVENT_OPTIONS_NO_CAPTURE);
      },
      methods: {
        isClickOut: function isClickOut(evt) {
          return !contains(this.$el, evt.target);
        },
        _clickOutHandler: function _clickOutHandler(evt) {
          if (this.clickOutHandler && this.isClickOut(evt)) {
            this.clickOutHandler(evt);
          }
        }
      }
    };
  
    var focusInMixin = {
      data: function data() {
        return {
          listenForFocusIn: false
        };
      },
      watch: {
        listenForFocusIn: function listenForFocusIn(newValue, oldValue) {
          if (newValue !== oldValue) {
            eventOff(this.focusInElement, 'focusin', this._focusInHandler, EVENT_OPTIONS_NO_CAPTURE);
  
            if (newValue) {
              eventOn(this.focusInElement, 'focusin', this._focusInHandler, EVENT_OPTIONS_NO_CAPTURE);
            }
          }
        }
      },
      beforeCreate: function beforeCreate() {
        // Declare non-reactive properties
        this.focusInElement = null;
      },
      mounted: function mounted() {
        if (!this.focusInElement) {
          this.focusInElement = document;
        }
  
        if (this.listenForFocusIn) {
          eventOn(this.focusInElement, 'focusin', this._focusInHandler, EVENT_OPTIONS_NO_CAPTURE);
        }
      },
      beforeDestroy: function beforeDestroy()
      /* istanbul ignore next */
      {
        eventOff(this.focusInElement, 'focusin', this._focusInHandler, EVENT_OPTIONS_NO_CAPTURE);
      },
      methods: {
        _focusInHandler: function _focusInHandler(evt) {
          if (this.focusInHandler) {
            this.focusInHandler(evt);
          }
        }
      }
    };
  
    var filterVisibles = function filterVisibles(els) {
      return (els || []).filter(isVisible);
    }; // Root dropdown event names
  
  
    var ROOT_DROPDOWN_PREFIX = 'bv::dropdown::';
    var ROOT_DROPDOWN_SHOWN = "".concat(ROOT_DROPDOWN_PREFIX, "shown");
    var ROOT_DROPDOWN_HIDDEN = "".concat(ROOT_DROPDOWN_PREFIX, "hidden"); // Dropdown item CSS selectors
  
    var Selector = {
      FORM_CHILD: '.dropdown form',
      ITEM_SELECTOR: ['.dropdown-item', '.b-dropdown-form'].map(function (selector) {
        return "".concat(selector, ":not(.disabled):not([disabled])");
      }).join(', ')
    }; // 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',
      // Dropright left align
      RIGHT: 'right-start',
      // Dropright right align
      RIGHTEND: 'right-end',
      // Dropleft left align
      LEFT: 'left-start',
      // Dropleft right align
      LEFTEND: 'left-end'
    };
    var commonProps = {
      dropup: {
        // place on top if possible
        type: Boolean,
        default: false
      },
      dropright: {
        // place right if possible
        type: Boolean,
        default: false
      },
      dropleft: {
        // place left 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() {}
      },
      boundary: {
        // String: `scrollParent`, `window` or `viewport`
        // HTMLElement: HTML Element reference
        type: [String, HTMLElement],
        default: 'scrollParent'
      }
    }; // @vue/component
  
    var dropdownMixin = {
      mixins: [idMixin, clickOutMixin, focusInMixin],
      provide: function provide() {
        return {
          bvDropdown: this
        };
      },
      inject: {
        bvNavbar: {
          default: null
        }
      },
      props: _objectSpread2({
        disabled: {
          type: Boolean,
          default: false
        }
      }, commonProps),
      data: function data() {
        return {
          visible: false,
          visibleChangePrevented: false
        };
      },
      computed: {
        inNavbar: function inNavbar() {
          return !isNull(this.bvNavbar);
        },
        toggler: function toggler() {
          var toggle = this.$refs.toggle;
          return toggle ? toggle.$el || toggle : null;
        },
        directionClass: function directionClass() {
          if (this.dropup) {
            return 'dropup';
          } else if (this.dropright) {
            return 'dropright';
          } else if (this.dropleft) {
            return 'dropleft';
          }
  
          return '';
        }
      },
      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,
              componentId: this.safeId ? this.safeId() : this.id || null
            });
            this.emitEvent(bvEvt);
  
            if (bvEvt.defaultPrevented) {
              // Reset value and exit if canceled
              this.visibleChangePrevented = true;
              this.visible = oldValue; // Just in case a child element triggered `this.hide(true)`
  
              this.$off('hidden', this.focusToggler);
              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;
          }
        }
      },
      created: function created() {
        // Create non-reactive property
        this.$_popper = null;
      },
      deactivated: function deactivated()
      /* istanbul ignore next: not easy to test */
      {
        // In case we are inside a `<keep-alive>`
        this.visible = false;
        this.whileOpenListen(false);
        this.destroyPopper();
      },
      beforeDestroy: function beforeDestroy() {
        this.visible = false;
        this.whileOpenListen(false);
        this.destroyPopper();
      },
      methods: {
        // Event emitter
        emitEvent: function emitEvent(bvEvt) {
          var type = bvEvt.type;
          this.$emit(type, bvEvt);
          this.$root.$emit("".concat(ROOT_DROPDOWN_PREFIX).concat(type), bvEvt);
        },
        showMenu: function showMenu() {
          var _this = this;
  
          if (this.disabled) {
            /* istanbul ignore next */
            return;
          } // Only instantiate Popper.js when dropdown is not in `<b-navbar>`
  
  
          if (!this.inNavbar) {
            if (typeof Popper === 'undefined') {
              /* istanbul ignore next */
              warn('Popper.js not found. Falling back to CSS positioning', 'BDropdown');
            } else {
              // For dropup with alignment we use the parent element as popper container
              var el = this.dropup && this.right || this.split ? this.$el : this.$refs.toggle; // Make sure we have a reference to an element, not a component!
  
              el = el.$el || el; // Instantiate Popper.js
  
              this.createPopper(el);
            }
          } // Ensure other menus are closed
  
  
          this.$root.$emit(ROOT_DROPDOWN_SHOWN, this); // Enable listeners
  
          this.whileOpenListen(true); // Wrap in `$nextTick()` to ensure menu is fully rendered/shown
  
          this.$nextTick(function () {
            // Focus on the menu container on show
            _this.focusMenu(); // Emit the shown event
  
  
            _this.$emit('shown');
          });
        },
        hideMenu: function hideMenu() {
          this.whileOpenListen(false);
          this.$root.$emit(ROOT_DROPDOWN_HIDDEN, this);
          this.$emit('hidden');
          this.destroyPopper();
        },
        createPopper: function createPopper(element) {
          this.destroyPopper();
          this.$_popper = new Popper(element, this.$refs.menu, this.getPopperConfig());
        },
        destroyPopper: function destroyPopper() {
          // Ensure popper event listeners are removed cleanly
          if (this.$_popper) {
            this.$_popper.destroy();
          }
  
          this.$_popper = null;
        },
        updatePopper: function updatePopper()
        /* istanbul ignore next: not easy to test */
        {
          // Instructs popper to re-computes the dropdown position
          // usefull if the content changes size
          try {
            this.$_popper.scheduleUpdate();
          } catch (_unused) {}
        },
        getPopperConfig: function getPopperConfig() {
          var placement = AttachmentMap.BOTTOM;
  
          if (this.dropup) {
            placement = this.right ? AttachmentMap.TOPEND : AttachmentMap.TOP;
          } else if (this.dropright) {
            placement = AttachmentMap.RIGHT;
          } else if (this.dropleft) {
            placement = AttachmentMap.LEFT;
          } else if (this.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 _objectSpread2({}, popperConfig, {}, this.popperOpts || {});
        },
        // Turn listeners on/off while open
        whileOpenListen: function whileOpenListen(isOpen) {
          // Hide the dropdown when clicked outside
          this.listenForClickOut = isOpen; // Hide the dropdown when it loses focus
  
          this.listenForFocusIn = isOpen; // Hide the dropdown when another dropdown is opened
  
          var method = isOpen ? '$on' : '$off';
          this.$root[method](ROOT_DROPDOWN_SHOWN, this.rootCloseListener);
        },
        rootCloseListener: function rootCloseListener(vm) {
          if (vm !== this) {
            this.visible = false;
          }
        },
        show: function show() {
          var _this2 = this;
  
          // Public method to show dropdown
          if (this.disabled) {
            return;
          } // Wrap in a `requestAF()` to allow any previous
          // click handling to occur first
  
  
          requestAF(function () {
            _this2.visible = true;
          });
        },
        hide: function hide() {
          var refocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  
          // Public method to hide dropdown
          if (this.disabled) {
            /* istanbul ignore next */
            return;
          }
  
          this.visible = false;
  
          if (refocus) {
            // Child element is closing the dropdown on click
            this.$once('hidden', this.focusToggler);
          }
        },
        // Called only by a button that toggles the menu
        toggle: function toggle(evt) {
          evt = evt || {}; // Early exit when not a click event or ENTER, SPACE or DOWN were pressed
  
          var _evt = evt,
              type = _evt.type,
              keyCode = _evt.keyCode;
  
          if (type !== 'click' && !(type === 'keydown' && [KEY_CODES.ENTER, KEY_CODES.SPACE, KEY_CODES.DOWN].indexOf(keyCode) !== -1)) {
            /* istanbul ignore next */
            return;
          }
          /* istanbul ignore next */
  
  
          if (this.disabled) {
            this.visible = false;
            return;
          }
  
          this.$emit('toggle', evt);
          evt.preventDefault();
          evt.stopPropagation(); // Toggle visibility
  
          if (this.visible) {
            this.hide(true);
          } else {
            this.show();
          }
        },
        // Mousedown handler for the toggle
        onMousedown: function onMousedown(evt)
        /* istanbul ignore next */
        {
          // We prevent the 'mousedown' event for the toggle to stop the
          // 'focusin' event from being fired
          // The event would otherwise be picked up by the global 'focusin'
          // listener and there is no cross-browser solution to detect it
          // relates to the toggle click
          // The 'click' event will still be fired and we handle closing
          // other dropdowns there too
          // See https://github.com/bootstrap-vue/bootstrap-vue/issues/4328
          evt.preventDefault();
        },
        // Called from dropdown menu context
        onKeydown: function onKeydown(evt) {
          var keyCode = evt.keyCode;
  
          if (keyCode === KEY_CODES.ESC) {
            // Close on ESC
            this.onEsc(evt);
          } else if (keyCode === KEY_CODES.DOWN) {
            // Down Arrow
            this.focusNext(evt, false);
          } else if (keyCode === KEY_CODES.UP) {
            // Up Arrow
            this.focusNext(evt, true);
          }
        },
        // If user presses ESC, close the menu
        onEsc: function onEsc(evt) {
          if (this.visible) {
            this.visible = false;
            evt.preventDefault();
            evt.stopPropagation(); // Return focus to original trigger button
  
            this.$once('hidden', this.focusToggler);
          }
        },
        // Called only in split button mode, for the split button
        onSplitClick: function onSplitClick(evt) {
          /* istanbul ignore next */
          if (this.disabled) {
            this.visible = false;
            return;
          }
  
          this.$emit('click', evt);
        },
        // Shared hide handler between click-out and focus-in events
        hideHandler: function hideHandler(evt) {
          var target = evt.target;
  
          if (this.visible && !contains(this.$refs.menu, target) && !contains(this.toggler, target)) {
            this.hide();
          }
        },
        // Document click-out listener
        clickOutHandler: function clickOutHandler(evt) {
          this.hideHandler(evt);
        },
        // Document focus-in listener
        focusInHandler: function focusInHandler(evt) {
          this.hideHandler(evt);
        },
        // Keyboard nav
        focusNext: function focusNext(evt, up) {
          var _this3 = this;
  
          // Ignore key up/down on form elements
          var target = evt.target;
  
          if (!this.visible || evt && closest(Selector.FORM_CHILD, target)) {
            /* istanbul ignore next: should never happen */
            return;
          }
  
          evt.preventDefault();
          evt.stopPropagation();
          this.$nextTick(function () {
            var items = _this3.getItems();
  
            if (items.length < 1) {
              /* istanbul ignore next: should never happen */
              return;
            }
  
            var index = items.indexOf(target);
  
            if (up && index > 0) {
              index--;
            } else if (!up && index < items.length - 1) {
              index++;
            }
  
            if (index < 0) {
              /* istanbul ignore next: should never happen */
              index = 0;
            }
  
            _this3.focusItem(index, items);
          });
        },
        focusItem: function focusItem(idx, items) {
          var el = items.find(function (el, i) {
            return i === idx;
          });
  
          if (el && el.focus) {
            el.focus();
          }
        },
        getItems: function getItems() {
          // Get all items
          return filterVisibles(selectAll(Selector.ITEM_SELECTOR, this.$refs.menu));
        },
        focusMenu: function focusMenu() {
          try {
            this.$refs.menu.focus();
          } catch (_unused2) {}
        },
        focusToggler: function focusToggler() {
          var _this4 = this;
  
          this.$nextTick(function () {
            var toggler = _this4.toggler;
  
            if (toggler && toggler.focus) {
              toggler.focus();
            }
          });
        }
      }
    };
  
    var NAME$b = 'BDropdown';
    var props$j = {
      text: {
        // Button label
        type: String,
        default: ''
      },
      html: {
        // Button label
        type: String
      },
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$b, 'size');
        }
      },
      variant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$b, 'variant');
        }
      },
      block: {
        type: Boolean,
        default: false
      },
      menuClass: {
        type: [String, Array, Object],
        default: null
      },
      toggleTag: {
        type: String,
        default: 'button'
      },
      toggleText: {
        // This really should be toggleLabel
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$b, 'toggleText');
        }
      },
      toggleClass: {
        type: [String, Array, Object],
        default: null
      },
      noCaret: {
        type: Boolean,
        default: false
      },
      split: {
        type: Boolean,
        default: false
      },
      splitHref: {
        type: String // default: undefined
  
      },
      splitTo: {
        type: [String, Object] // default: undefined
  
      },
      splitVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$b, 'splitVariant');
        }
      },
      splitClass: {
        type: [String, Array, Object],
        default: null
      },
      splitButtonType: {
        type: String,
        default: 'button',
        validator: function validator(value) {
          return arrayIncludes(['button', 'submit', 'reset'], value);
        }
      },
      lazy: {
        // If true, only render menu contents when open
        type: Boolean,
        default: false
      },
      role: {
        type: String,
        default: 'menu'
      }
    }; // @vue/component
  
    var BDropdown = /*#__PURE__*/Vue.extend({
      name: NAME$b,
      mixins: [idMixin, dropdownMixin, normalizeSlotMixin],
      props: props$j,
      computed: {
        dropdownClasses: function dropdownClasses() {
          return [this.directionClass, {
            show: this.visible,
            // The 'btn-group' class is required in `split` mode for button alignment
            // It needs also to be applied when `block` is disabled to allow multiple
            // dropdowns to be aligned one line
            'btn-group': this.split || !this.block,
            // When `block` is enabled and we are in `split` mode the 'd-flex' class
            // needs to be applied to allow the buttons to stretch to full width
            'd-flex': this.block && this.split,
            // 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
            'position-static': this.boundary !== 'scrollParent' || !this.boundary
          }];
        },
        menuClasses: function menuClasses() {
          return [this.menuClass, {
            'dropdown-menu-right': this.right,
            show: this.visible
          }];
        },
        toggleClasses: function toggleClasses() {
          return [this.toggleClass, {
            'dropdown-toggle-split': this.split,
            'dropdown-toggle-no-caret': this.noCaret && !this.split
          }];
        }
      },
      render: function render(h) {
        var split = h();
        var buttonContent = this.normalizeSlot('button-content') || this.html || stripTags(this.text);
  
        if (this.split) {
          var btnProps = {
            variant: this.splitVariant || this.variant,
            size: this.size,
            block: this.block,
            disabled: this.disabled
          }; // We add these as needed due to router-link issues with defined property with undefined/null values
  
          if (this.splitTo) {
            btnProps.to = this.splitTo;
          } else if (this.splitHref) {
            btnProps.href = this.splitHref;
          } else if (this.splitButtonType) {
            btnProps.type = this.splitButtonType;
          }
  
          split = h(BButton, {
            ref: 'button',
            props: btnProps,
            class: this.splitClass,
            attrs: {
              id: this.safeId('_BV_button_')
            },
            on: {
              click: this.onSplitClick
            }
          }, [buttonContent]);
        }
  
        var toggle = h(BButton, {
          ref: 'toggle',
          staticClass: 'dropdown-toggle',
          class: this.toggleClasses,
          props: {
            tag: this.toggleTag,
            variant: this.variant,
            size: this.size,
            block: this.block && !this.split,
            disabled: this.disabled
          },
          attrs: {
            id: this.safeId('_BV_toggle_'),
            'aria-haspopup': 'true',
            'aria-expanded': this.visible ? 'true' : 'false'
          },
          on: {
            mousedown: this.onMousedown,
            click: this.toggle,
            keydown: this.toggle // Handle ENTER, SPACE and DOWN
  
          }
        }, [this.split ? h('span', {
          class: ['sr-only']
        }, [this.toggleText]) : buttonContent]);
        var menu = h('ul', {
          ref: 'menu',
          staticClass: 'dropdown-menu',
          class: this.menuClasses,
          attrs: {
            role: this.role,
            tabindex: '-1',
            'aria-labelledby': this.safeId(this.split ? '_BV_button_' : '_BV_toggle_')
          },
          on: {
            keydown: this.onKeydown // Handle UP, DOWN and ESC
  
          }
        }, !this.lazy || this.visible ? this.normalizeSlot('default', {
          hide: this.hide
        }) : [h()]);
        return h('div', {
          staticClass: 'dropdown b-dropdown',
          class: this.dropdownClasses,
          attrs: {
            id: this.safeId()
          }
        }, [split, toggle, menu]);
      }
    });
  
    var props$k = propsFactory(); // @vue/component
  
    var BDropdownItem = /*#__PURE__*/Vue.extend({
      name: 'BDropdownItem',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      inject: {
        bvDropdown: {
          default: null
        }
      },
      props: _objectSpread2({}, props$k, {
        variant: {
          type: String,
          default: null
        }
      }),
      methods: {
        closeDropdown: function closeDropdown() {
          var _this = this;
  
          // Close on next animation frame to allow <b-link> time to process
          requestAF(function () {
            if (_this.bvDropdown) {
              _this.bvDropdown.hide(true);
            }
          });
        },
        onClick: function onClick(evt) {
          this.$emit('click', evt);
          this.closeDropdown();
        }
      },
      render: function render(h) {
        return h('li', {
          attrs: {
            role: 'presentation'
          }
        }, [h(BLink, {
          props: this.$props,
          staticClass: 'dropdown-item',
          class: _defineProperty({}, "text-".concat(this.variant), this.variant && !(this.active || this.disabled)),
          attrs: _objectSpread2({}, this.$attrs, {
            role: 'menuitem'
          }),
          on: {
            click: this.onClick
          },
          ref: 'item'
        }, this.normalizeSlot('default'))]);
      }
    });
  
    var props$l = {
      active: {
        type: Boolean,
        default: false
      },
      activeClass: {
        type: String,
        default: 'active'
      },
      disabled: {
        type: Boolean,
        default: false
      },
      variant: {
        type: String,
        default: null
      }
    }; // @vue/component
  
    var BDropdownItemButton = /*#__PURE__*/Vue.extend({
      name: 'BDropdownItemButton',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      inject: {
        bvDropdown: {
          default: null
        }
      },
      props: props$l,
      methods: {
        closeDropdown: function closeDropdown() {
          if (this.bvDropdown) {
            this.bvDropdown.hide(true);
          }
        },
        onClick: function onClick(evt) {
          this.$emit('click', evt);
          this.closeDropdown();
        }
      },
      render: function render(h) {
        var _class;
  
        return h('li', {
          attrs: {
            role: 'presentation'
          }
        }, [h('button', {
          staticClass: 'dropdown-item',
          class: (_class = {}, _defineProperty(_class, this.activeClass, this.active), _defineProperty(_class, "text-".concat(this.variant), this.variant && !(this.active || this.disabled)), _class),
          attrs: _objectSpread2({}, this.$attrs, {
            role: 'menuitem',
            type: 'button',
            disabled: this.disabled
          }),
          on: {
            click: this.onClick
          },
          ref: 'button'
        }, this.normalizeSlot('default'))]);
      }
    });
  
    var props$m = {
      id: {
        type: String,
        default: null
      },
      tag: {
        type: String,
        default: 'header'
      },
      variant: {
        type: String,
        default: null
      }
    }; // @vue/component
  
    var BDropdownHeader = /*#__PURE__*/Vue.extend({
      name: 'BDropdownHeader',
      functional: true,
      props: props$m,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var $attrs = data.attrs || {};
        data.attrs = {};
        return h('li', a(data, {
          attrs: {
            role: 'presentation'
          }
        }), [h(props.tag, {
          staticClass: 'dropdown-header',
          class: _defineProperty({}, "text-".concat(props.variant), props.variant),
          attrs: _objectSpread2({}, $attrs, {
            id: props.id || null,
            role: 'heading'
          }),
          ref: 'header'
        }, children)]);
      }
    });
  
    var props$n = {
      tag: {
        type: String,
        default: 'hr'
      }
    }; // @vue/component
  
    var BDropdownDivider = /*#__PURE__*/Vue.extend({
      name: 'BDropdownDivider',
      functional: true,
      props: props$n,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data;
        var $attrs = data.attrs || {};
        data.attrs = {};
        return h('li', a(data, {
          attrs: {
            role: 'presentation'
          }
        }), [h(props.tag, {
          staticClass: 'dropdown-divider',
          attrs: _objectSpread2({}, $attrs, {
            role: 'separator',
            'aria-orientation': 'horizontal'
          }),
          ref: 'divider'
        })]);
      }
    });
  
    var props$o = {
      id: {
        type: String,
        default: null
      },
      inline: {
        type: Boolean,
        default: false
      },
      novalidate: {
        type: Boolean,
        default: false
      },
      validated: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BForm = /*#__PURE__*/Vue.extend({
      name: 'BForm',
      functional: true,
      props: props$o,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h('form', a(data, {
          class: {
            'form-inline': props.inline,
            'was-validated': props.validated
          },
          attrs: {
            id: props.id,
            novalidate: props.novalidate
          }
        }), children);
      }
    });
  
    var BDropdownForm = /*#__PURE__*/Vue.extend({
      name: 'BDropdownForm',
      functional: true,
      props: _objectSpread2({}, props$o, {
        disabled: {
          type: Boolean,
          default: false
        },
        formClass: {
          type: [String, Object, Array],
          default: null
        }
      }),
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var $attrs = data.attrs || {};
        var $listeners = data.on || {};
        data.attrs = {};
        data.on = {};
        return h('li', a(data, {
          attrs: {
            role: 'presentation'
          }
        }), [h(BForm, {
          ref: 'form',
          staticClass: 'b-dropdown-form',
          class: [props.formClass, {
            disabled: props.disabled
          }],
          props: props,
          attrs: _objectSpread2({}, $attrs, {
            disabled: props.disabled,
            // Tab index of -1 for keyboard navigation
            tabindex: props.disabled ? null : '-1'
          }),
          on: $listeners
        }, children)]);
      }
    });
  
    var BDropdownText = /*#__PURE__*/Vue.extend({
      name: 'BDropdownText',
      functional: true,
      props: {
        tag: {
          type: String,
          default: 'p'
        },
        variant: {
          type: String,
          default: null
        }
      },
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var $attrs = data.attrs || {};
        data.attrs = {};
        return h('li', a(data, {
          attrs: {
            role: 'presentation'
          }
        }), [h(props.tag, {
          staticClass: 'b-dropdown-text',
          class: _defineProperty({}, "text-".concat(props.variant), props.variant),
          props: props,
          attrs: $attrs,
          ref: 'text'
        }, children)]);
      }
    });
  
    var props$p = {
      id: {
        type: String,
        default: null
      },
      header: {
        type: String,
        default: null
      },
      headerTag: {
        type: String,
        default: 'header'
      },
      headerVariant: {
        type: String,
        default: null
      },
      headerClasses: {
        type: [String, Array, Object],
        default: null
      },
      ariaDescribedby: {
        type: String,
        default: null
      }
    }; // @vue/component
  
    var BDropdownGroup = /*#__PURE__*/Vue.extend({
      name: 'BDropdownGroup',
      functional: true,
      props: props$p,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots;
        var $slots = slots();
        var $scopedSlots = scopedSlots || {};
        var $attrs = data.attrs || {};
        data.attrs = {};
        var header;
        var headerId = null;
  
        if (hasNormalizedSlot('header', $scopedSlots, $slots) || props.header) {
          headerId = props.id ? "_bv_".concat(props.id, "_group_dd_header") : null;
          header = h(props.headerTag, {
            staticClass: 'dropdown-header',
            class: [props.headerClasses, _defineProperty({}, "text-".concat(props.variant), props.variant)],
            attrs: {
              id: headerId,
              role: 'heading'
            }
          }, normalizeSlot('header', {}, $scopedSlots, $slots) || props.header);
        }
  
        var adb = [headerId, props.ariaDescribedBy].filter(Boolean).join(' ').trim();
        return h('li', a(data, {
          attrs: {
            role: 'presentation'
          }
        }), [header || h(), h('ul', {
          staticClass: 'list-unstyled',
          attrs: _objectSpread2({}, $attrs, {
            id: props.id || null,
            role: 'group',
            'aria-describedby': adb || null
          })
        }, normalizeSlot('default', {}, $scopedSlots, $slots))]);
      }
    });
  
    var DropdownPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BDropdown: BDropdown,
        BDd: BDropdown,
        BDropdownItem: BDropdownItem,
        BDdItem: BDropdownItem,
        BDropdownItemButton: BDropdownItemButton,
        BDropdownItemBtn: BDropdownItemButton,
        BDdItemButton: BDropdownItemButton,
        BDdItemBtn: BDropdownItemButton,
        BDropdownHeader: BDropdownHeader,
        BDdHeader: BDropdownHeader,
        BDropdownDivider: BDropdownDivider,
        BDdDivider: BDropdownDivider,
        BDropdownForm: BDropdownForm,
        BDdForm: BDropdownForm,
        BDropdownText: BDropdownText,
        BDdText: BDropdownText,
        BDropdownGroup: BDropdownGroup,
        BDdGroup: BDropdownGroup
      }
    });
  
    var props$q = {
      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'
      }
    }; // @vue/component
  
    var BEmbed = /*#__PURE__*/Vue.extend({
      name: 'BEmbed',
      functional: true,
      props: props$q,
      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-".concat(props.aspect), props.aspect)
        }, [h(props.type, a(data, {
          ref: '',
          staticClass: 'embed-responsive-item'
        }), children)]);
      }
    });
  
    var EmbedPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BEmbed: BEmbed
      }
    });
  
    var OPTIONS_OBJECT_DEPRECATED_MSG = 'Setting prop "options" to an object is deprecated. Use the array format instead.'; // @vue/component
  
    var formOptionsMixin = {
      props: {
        options: {
          type: [Array, Object],
          default: function _default() {
            return [];
          }
        },
        valueField: {
          type: String,
          default: 'value'
        },
        textField: {
          type: String,
          default: 'text'
        },
        htmlField: {
          type: String,
          default: 'html'
        },
        disabledField: {
          type: String,
          default: 'disabled'
        }
      },
      computed: {
        formOptions: function formOptions() {
          var _this = this;
  
          var options = this.options; // Normalize the given options array
  
          if (isArray(options)) {
            return options.map(function (option) {
              return _this.normalizeOption(option);
            });
          } // Deprecate the object options format
  
  
          warn(OPTIONS_OBJECT_DEPRECATED_MSG, this.$options.name); // Normalize a `options` object to an array of options
  
          return keys(options).map(function (key) {
            return _this.normalizeOption(options[key] || {}, key);
          });
        }
      },
      methods: {
        normalizeOption: function normalizeOption(option) {
          var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  
          // When the option is an object, normalize it
          if (isPlainObject(option)) {
            var value = get(option, this.valueField);
            var text = get(option, this.textField);
            return {
              value: isUndefined(value) ? key || text : value,
              text: stripTags(String(isUndefined(text) ? key : text)),
              html: get(option, this.htmlField),
              disabled: Boolean(get(option, this.disabledField))
            };
          } // Otherwise create an `<option>` object from the given value
  
  
          return {
            value: key || option,
            text: stripTags(String(option)),
            disabled: false
          };
        }
      }
    };
  
    var BFormDatalist = /*#__PURE__*/Vue.extend({
      name: 'BFormDatalist',
      mixins: [formOptionsMixin, normalizeSlotMixin],
      props: {
        id: {
          type: String,
          default: null,
          required: true
        }
      },
      render: function render(h) {
        var options = this.formOptions.map(function (option, index) {
          return h('option', {
            key: "option_".concat(index, "_opt"),
            attrs: {
              disabled: option.disabled
            },
            domProps: _objectSpread2({}, htmlOrText(option.html, option.text), {
              value: option.value
            })
          });
        });
        return h('datalist', {
          attrs: {
            id: this.id
          }
        }, [options, this.normalizeSlot('default')]);
      }
    });
  
    var NAME$c = 'BFormText';
    var props$r = {
      id: {
        type: String,
        default: null
      },
      tag: {
        type: String,
        default: 'small'
      },
      textVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$c, 'textVariant');
        }
      },
      inline: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BFormText = /*#__PURE__*/Vue.extend({
      name: NAME$c,
      functional: true,
      props: props$r,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          class: _defineProperty({
            'form-text': !props.inline
          }, "text-".concat(props.textVariant), props.textVariant),
          attrs: {
            id: props.id
          }
        }), children);
      }
    });
  
    var props$s = {
      id: {
        type: String,
        default: null
      },
      tag: {
        type: String,
        default: 'div'
      },
      tooltip: {
        type: Boolean,
        default: false
      },
      forceShow: {
        type: Boolean,
        default: false
      },
      state: {
        type: Boolean,
        default: null
      },
      ariaLive: {
        type: String,
        default: null
      },
      role: {
        type: String,
        default: null
      }
    }; // @vue/component
  
    var BFormInvalidFeedback = /*#__PURE__*/Vue.extend({
      name: 'BFormInvalidFeedback',
      functional: true,
      props: props$s,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var show = props.forceShow === true || props.state === false;
        return h(props.tag, a(data, {
          class: {
            'invalid-feedback': !props.tooltip,
            'invalid-tooltip': props.tooltip,
            'd-block': show
          },
          attrs: {
            id: props.id,
            role: props.role,
            'aria-live': props.ariaLive,
            'aria-atomic': props.ariaLive ? 'true' : null
          }
        }), children);
      }
    });
  
    var props$t = {
      id: {
        type: String,
        default: null
      },
      tag: {
        type: String,
        default: 'div'
      },
      tooltip: {
        type: Boolean,
        default: false
      },
      forceShow: {
        type: Boolean,
        default: false
      },
      state: {
        type: Boolean,
        default: null
      },
      ariaLive: {
        type: String,
        default: null
      },
      role: {
        type: String,
        default: null
      }
    }; // @vue/component
  
    var BFormValidFeedback = /*#__PURE__*/Vue.extend({
      name: 'BFormValidFeedback',
      functional: true,
      props: props$t,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var show = props.forceShow === true || props.state === true;
        return h(props.tag, a(data, {
          class: {
            'valid-feedback': !props.tooltip,
            'valid-tooltip': props.tooltip,
            'd-block': show
          },
          attrs: {
            id: props.id,
            role: props.role,
            'aria-live': props.ariaLive,
            'aria-atomic': props.ariaLive ? 'true' : null
          }
        }), children);
      }
    });
  
    var props$u = {
      tag: {
        type: String,
        default: 'div'
      }
    }; // @vue/component
  
    var BFormRow = /*#__PURE__*/Vue.extend({
      name: 'BFormRow',
      functional: true,
      props: props$u,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          staticClass: 'form-row'
        }), children);
      }
    });
  
    var FormPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BForm: BForm,
        BFormDatalist: BFormDatalist,
        BDatalist: BFormDatalist,
        BFormText: BFormText,
        BFormInvalidFeedback: BFormInvalidFeedback,
        BFormFeedback: BFormInvalidFeedback,
        BFormValidFeedback: BFormValidFeedback,
        // Added here for convenience
        BFormRow: BFormRow
      }
    }); // BFormRow is not exported here as a named export, as it is exported by Layout
  
    var looseIndexOf = function looseIndexOf(arr, val) {
      // Assumes that the first argument is an array
      for (var i = 0; i < arr.length; i++) {
        if (looseEqual(arr[i], val)) {
          return i;
        }
      }
  
      return -1;
    };
  
    var SELECTOR = 'input, textarea, select'; // @vue/component
  
    var formMixin = {
      props: {
        name: {
          type: String // default: undefined
  
        },
        id: {
          type: String // default: undefined
  
        },
        disabled: {
          type: Boolean
        },
        required: {
          type: Boolean,
          default: false
        },
        form: {
          type: String,
          default: null
        },
        autofocus: {
          type: Boolean,
          default: false
        }
      },
      mounted: function mounted() {
        this.handleAutofocus();
      },
      activated: function activated()
      /* istanbul ignore next */
      {
        this.handleAutofocus();
      },
      methods: {
        handleAutofocus: function handleAutofocus() {
          var _this = this;
  
          this.$nextTick(function () {
            requestAF(function () {
              var el = _this.$el;
  
              if (_this.autofocus && isVisible(el)) {
                if (!matches(el, SELECTOR)) {
                  el = select(SELECTOR, el);
                }
  
                el && el.focus && el.focus();
              }
            });
          });
        }
      }
    };
  
    var formRadioCheckMixin = {
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      model: {
        prop: 'checked',
        event: 'input'
      },
      props: {
        value: {// Value when checked
          // type: Object,
          // default: undefined
        },
        checked: {// This is the v-model
          // type: Object,
          // default: undefined
        },
        inline: {
          type: Boolean,
          default: false
        },
        plain: {
          type: Boolean,
          default: false
        },
        button: {
          // Only applicable in standalone mode (non group)
          type: Boolean,
          default: false
        },
        buttonVariant: {
          // Only applicable when rendered with button style
          type: String,
          default: null
        },
        ariaLabel: {
          // Placed on the input if present.
          type: String,
          default: null
        },
        ariaLabelledby: {
          // Placed on the input if present.
          type: String,
          default: null
        }
      },
      data: function data() {
        return {
          localChecked: this.isGroup ? this.bvGroup.checked : this.checked,
          hasFocus: false
        };
      },
      computed: {
        computedLocalChecked: {
          get: function get() {
            return this.isGroup ? this.bvGroup.localChecked : this.localChecked;
          },
          set: function set(val) {
            if (this.isGroup) {
              this.bvGroup.localChecked = val;
            } else {
              this.localChecked = val;
            }
          }
        },
        isGroup: function isGroup() {
          // Is this check/radio a child of check-group or radio-group?
          return Boolean(this.bvGroup);
        },
        isBtnMode: function isBtnMode() {
          // Support button style in single input mode
          return this.isGroup ? this.bvGroup.buttons : this.button;
        },
        isPlain: function isPlain() {
          return this.isBtnMode ? false : this.isGroup ? this.bvGroup.plain : this.plain;
        },
        isCustom: function isCustom() {
          return this.isBtnMode ? false : !this.isPlain;
        },
        isSwitch: function isSwitch() {
          // Custom switch styling (checkboxes only)
          return this.isBtnMode || this.isRadio || this.isPlain ? false : this.isGroup ? this.bvGroup.switches : this.switch;
        },
        isInline: function isInline() {
          return this.isGroup ? this.bvGroup.inline : this.inline;
        },
        isDisabled: function isDisabled() {
          // Child can be disabled while parent isn't, but is always disabled if group is
          return this.isGroup ? this.bvGroup.disabled || this.disabled : this.disabled;
        },
        isRequired: function isRequired() {
          // Required only works when a name is provided for the input(s)
          // Child can only be required when parent is
          // Groups will always have a name (either user supplied or auto generated)
          return this.getName && (this.isGroup ? this.bvGroup.required : this.required);
        },
        getName: function getName() {
          // Group name preferred over local name
          return (this.isGroup ? this.bvGroup.groupName : this.name) || null;
        },
        getForm: function getForm() {
          return (this.isGroup ? this.bvGroup.form : this.form) || null;
        },
        getSize: function getSize() {
          return (this.isGroup ? this.bvGroup.size : this.size) || '';
        },
        getState: function getState() {
          return this.isGroup ? this.bvGroup.computedState : this.computedState;
        },
        getButtonVariant: function getButtonVariant() {
          // Local variant preferred over group variant
          if (this.buttonVariant) {
            return this.buttonVariant;
          } else if (this.isGroup && this.bvGroup.buttonVariant) {
            return this.bvGroup.buttonVariant;
          } // default variant
  
  
          return 'secondary';
        },
        buttonClasses: function buttonClasses() {
          var _ref;
  
          // Same for radio & check
          return ['btn', "btn-".concat(this.getButtonVariant), (_ref = {}, _defineProperty(_ref, "btn-".concat(this.getSize), this.getSize), _defineProperty(_ref, "disabled", this.isDisabled), _defineProperty(_ref, "active", this.isChecked), _defineProperty(_ref, "focus", this.hasFocus), _ref)];
        }
      },
      watch: {
        checked: function checked(newVal) {
          this.computedLocalChecked = newVal;
        }
      },
      methods: {
        handleFocus: function handleFocus(evt) {
          // When in buttons mode, we need to add 'focus' class to label when input focused
          // As it is the hidden input which has actual focus
          if (evt.target) {
            if (evt.type === 'focus') {
              this.hasFocus = true;
            } else if (evt.type === 'blur') {
              this.hasFocus = false;
            }
          }
        },
        // Convenience methods for focusing the input
        focus: function focus() {
          if (!this.isDisabled && this.$refs.input && this.$refs.input.focus) {
            this.$refs.input.focus();
          }
        },
        blur: function blur() {
          if (!this.isDisabled && this.$refs.input && this.$refs.input.blur) {
            this.$refs.input.blur();
          }
        }
      },
      render: function render(h) {
        var defaultSlot = this.normalizeSlot('default'); // Generate the input element
  
        var on = {
          change: this.handleChange
        };
  
        if (this.isBtnMode) {
          // Handlers for focus styling when in button mode
          on.focus = on.blur = this.handleFocus;
        }
  
        var input = h('input', {
          ref: 'input',
          key: 'input',
          on: on,
          class: {
            'form-check-input': this.isPlain,
            'custom-control-input': this.isCustom,
            'is-valid': this.getState === true && !this.isBtnMode,
            'is-invalid': this.getState === false && !this.isBtnMode,
            // https://github.com/bootstrap-vue/bootstrap-vue/issues/2911
            'position-static': this.isPlain && !defaultSlot
          },
          directives: [{
            name: 'model',
            rawName: 'v-model',
            value: this.computedLocalChecked,
            expression: 'computedLocalChecked'
          }],
          attrs: _objectSpread2({}, this.$attrs, {
            id: this.safeId(),
            type: this.isRadio ? 'radio' : 'checkbox',
            name: this.getName,
            form: this.getForm,
            disabled: this.isDisabled,
            required: this.isRequired,
            autocomplete: 'off',
            'aria-required': this.isRequired || null,
            'aria-label': this.ariaLabel || null,
            'aria-labelledby': this.ariaLabelledby || null
          }),
          domProps: {
            value: this.value,
            checked: this.isChecked
          }
        });
  
        if (this.isBtnMode) {
          // Button mode
          var button = h('label', {
            class: this.buttonClasses
          }, [input, defaultSlot]);
  
          if (!this.isGroup) {
            // Standalone button mode, so wrap in 'btn-group-toggle'
            // and flag it as inline-block to mimic regular buttons
            button = h('div', {
              class: ['btn-group-toggle', 'd-inline-block']
            }, [button]);
          }
  
          return button;
        } else {
          // Not button mode
          var label = h(); // If no label content in plain mode we dont render the label
          // https://github.com/bootstrap-vue/bootstrap-vue/issues/2911
  
          if (!(this.isPlain && !defaultSlot)) {
            label = h('label', {
              class: {
                'form-check-label': this.isPlain,
                'custom-control-label': this.isCustom
              },
              attrs: {
                for: this.safeId()
              }
            }, defaultSlot);
          } // Wrap it in a div
  
  
          return h('div', {
            class: _defineProperty({
              'form-check': this.isPlain,
              'form-check-inline': this.isPlain && this.isInline,
              'custom-control': this.isCustom,
              'custom-control-inline': this.isCustom && this.isInline,
              'custom-checkbox': this.isCustom && this.isCheck && !this.isSwitch,
              'custom-switch': this.isSwitch,
              'custom-radio': this.isCustom && this.isRadio
            }, "b-custom-control-".concat(this.getSize), Boolean(this.getSize && !this.isBtnMode))
          }, [input, label]);
        }
      }
    };
  
    var formSizeMixin = {
      props: {
        size: {
          type: String,
          default: function _default() {
            return getComponentConfig('formControls', 'size');
          }
        }
      },
      computed: {
        sizeFormClass: function sizeFormClass() {
          return [this.size ? "form-control-".concat(this.size) : null];
        },
        sizeBtnClass: function sizeBtnClass()
        /* istanbul ignore next: don't think this is used */
        {
          return [this.size ? "btn-".concat(this.size) : null];
        }
      }
    };
  
    /* 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 for is-valid
     *  - false for is-invalid
     *  - null for no contextual state
     */
  
    var formStateMixin = {
      props: {
        state: {
          // Tri-state prop: true, false, null (or undefined)
          type: Boolean,
          default: null
        }
      },
      computed: {
        computedState: function computedState() {
          // If not a boolean, ensure that value is null
          return isBoolean(this.state) ? this.state : null;
        },
        stateClass: function stateClass() {
          var state = this.computedState;
          return state === true ? 'is-valid' : state === false ? 'is-invalid' : null;
        }
      }
    };
  
    var BFormCheckbox = /*#__PURE__*/Vue.extend({
      name: 'BFormCheckbox',
      mixins: [formRadioCheckMixin, // Includes shared render function
      idMixin, formMixin, formSizeMixin, formStateMixin],
      inject: {
        bvGroup: {
          from: 'bvCheckGroup',
          default: false
        }
      },
      props: {
        value: {
          // type: [String, Number, Boolean, Object],
          default: true
        },
        uncheckedValue: {
          // type: [String, Number, Boolean, Object],
          // Not applicable in multi-check mode
          default: false
        },
        indeterminate: {
          // Not applicable in multi-check mode
          type: Boolean,
          default: false
        },
        switch: {
          // Custom switch styling
          type: Boolean,
          default: false
        },
        checked: {
          // v-model (Array when multiple checkboxes have same name)
          // type: [String, Number, Boolean, Object, Array],
          default: null
        }
      },
      computed: {
        isChecked: function isChecked() {
          var checked = this.computedLocalChecked;
          var value = this.value;
  
          if (isArray(checked)) {
            return looseIndexOf(checked, value) > -1;
          } else {
            return looseEqual(checked, value);
          }
        },
        isRadio: function isRadio() {
          return false;
        },
        isCheck: function isCheck() {
          return true;
        }
      },
      watch: {
        computedLocalChecked: function computedLocalChecked(newVal) {
          this.$emit('input', newVal);
  
          if (this.$refs && this.$refs.input) {
            this.$emit('update:indeterminate', this.$refs.input.indeterminate);
          }
        },
        indeterminate: function indeterminate(newVal) {
          this.setIndeterminate(newVal);
        }
      },
      mounted: function mounted() {
        // Set initial indeterminate state
        this.setIndeterminate(this.indeterminate);
      },
      methods: {
        handleChange: function handleChange(_ref) {
          var _ref$target = _ref.target,
              checked = _ref$target.checked,
              indeterminate = _ref$target.indeterminate;
          var localChecked = this.computedLocalChecked;
          var value = this.value;
          var isArr = isArray(localChecked);
          var uncheckedValue = isArr ? null : this.uncheckedValue; // Update computedLocalChecked
  
          if (isArr) {
            var idx = looseIndexOf(localChecked, value);
  
            if (checked && idx < 0) {
              // Add value to array
              localChecked = localChecked.concat(value);
            } else if (!checked && idx > -1) {
              // Remove value from array
              localChecked = localChecked.slice(0, idx).concat(localChecked.slice(idx + 1));
            }
          } else {
            localChecked = checked ? value : uncheckedValue;
          }
  
          this.computedLocalChecked = localChecked; // Change is only emitted on user interaction
  
          this.$emit('change', checked ? value : uncheckedValue); // If this is a child of form-checkbox-group, we emit a change event on it as well
  
          if (this.isGroup) {
            this.bvGroup.$emit('change', localChecked);
          }
  
          this.$emit('update:indeterminate', indeterminate);
        },
        setIndeterminate: function setIndeterminate(state) {
          // Indeterminate only supported in single checkbox mode
          if (isArray(this.computedLocalChecked)) {
            state = false;
          }
  
          if (this.$refs && this.$refs.input) {
            this.$refs.input.indeterminate = state; // Emit update event to prop
  
            this.$emit('update:indeterminate', state);
          }
        }
      }
    });
  
    var BFormRadio = /*#__PURE__*/Vue.extend({
      name: 'BFormRadio',
      mixins: [idMixin, formRadioCheckMixin, // Includes shared render function
      formMixin, formSizeMixin, formStateMixin],
      inject: {
        bvGroup: {
          from: 'bvRadioGroup',
          default: false
        }
      },
      props: {
        checked: {
          // v-model
          // type: [String, Number, Boolean, Object],
          default: null
        }
      },
      computed: {
        // Radio Groups can only have a single value, so determining if checked is simple
        isChecked: function isChecked() {
          return looseEqual(this.value, this.computedLocalChecked);
        },
        // Flags for form-radio-check mixin
        isRadio: function isRadio() {
          return true;
        },
        isCheck: function isCheck() {
          return false;
        }
      },
      watch: {
        // Radio Groups can only have a single value, so our watchers are simple
        computedLocalChecked: function computedLocalChecked() {
          this.$emit('input', this.computedLocalChecked);
        }
      },
      methods: {
        handleChange: function handleChange(_ref) {
          var checked = _ref.target.checked;
          var value = this.value;
          this.computedLocalChecked = value; // Change is only emitted on user interaction
  
          this.$emit('change', checked ? value : null); // If this is a child of form-radio-group, we emit a change event on it as well
  
          if (this.isGroup) {
            this.bvGroup.$emit('change', checked ? value : null);
          }
        }
      }
    });
  
    var formRadioCheckGroupMixin = {
      mixins: [normalizeSlotMixin],
      model: {
        prop: 'checked',
        event: 'input'
      },
      props: {
        validated: {
          type: Boolean,
          default: false
        },
        ariaInvalid: {
          type: [Boolean, String],
          default: false
        },
        stacked: {
          type: Boolean,
          default: false
        },
        plain: {
          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'
        }
      },
      computed: {
        inline: function inline() {
          return !this.stacked;
        },
        groupName: function groupName() {
          // Checks/Radios tied to the same model must have the same name,
          // especially for ARIA accessibility.
          return this.name || this.safeId();
        },
        groupClasses: function groupClasses() {
          if (this.buttons) {
            return ['btn-group-toggle', this.inline ? 'btn-group' : 'btn-group-vertical', this.size ? "btn-group-".concat(this.size) : '', this.validated ? "was-validated" : ''];
          }
  
          return [this.validated ? "was-validated" : ''];
        },
        computedAriaInvalid: function computedAriaInvalid() {
          var ariaInvalid = this.ariaInvalid;
  
          if (ariaInvalid === true || ariaInvalid === 'true' || ariaInvalid === '') {
            return 'true';
          }
  
          return this.computedState === false ? 'true' : null;
        }
      },
      watch: {
        checked: function checked(newVal) {
          this.localChecked = newVal;
        },
        localChecked: function localChecked(newVal) {
          this.$emit('input', newVal);
        }
      },
      render: function render(h) {
        var _this = this;
  
        var inputs = this.formOptions.map(function (option, idx) {
          var uid = "_BV_option_".concat(idx, "_");
          return h(_this.isRadioGroup ? BFormRadio : BFormCheckbox, {
            key: uid,
            props: {
              id: _this.safeId(uid),
              value: option.value,
              // Individual radios or checks can be disabled in a group
              disabled: option.disabled || false // We don't need to include these, since the input's will know they are inside here
              // name: this.groupName,
              // form: this.form || null,
              // required: Boolean(this.name && this.required)
  
            }
          }, [h('span', {
            domProps: htmlOrText(option.html, option.text)
          })]);
        });
        return h('div', {
          class: [this.groupClasses, 'bv-no-focus-ring'],
          attrs: {
            id: this.safeId(),
            role: this.isRadioGroup ? 'radiogroup' : 'group',
            // Tabindex to allow group to be focused
            // if needed by screen readers
            tabindex: '-1',
            'aria-required': this.required ? 'true' : null,
            'aria-invalid': this.computedAriaInvalid
          }
        }, [this.normalizeSlot('first'), inputs, this.normalizeSlot('default')]);
      }
    };
  
    var props$v = {
      switches: {
        // Custom switch styling
        type: Boolean,
        default: false
      },
      checked: {
        type: Array,
        default: null
      }
    }; // @vue/component
  
    var BFormCheckboxGroup = /*#__PURE__*/Vue.extend({
      name: 'BFormCheckboxGroup',
      mixins: [idMixin, formMixin, formRadioCheckGroupMixin, // Includes render function
      formOptionsMixin, formSizeMixin, formStateMixin],
      provide: function provide() {
        return {
          bvCheckGroup: this
        };
      },
      props: props$v,
      data: function data() {
        return {
          localChecked: this.checked || []
        };
      },
      computed: {
        isRadioGroup: function isRadioGroup() {
          return false;
        }
      }
    });
  
    var FormCheckboxPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormCheckbox: BFormCheckbox,
        BCheckbox: BFormCheckbox,
        BCheck: BFormCheckbox,
        BFormCheckboxGroup: BFormCheckboxGroup,
        BCheckboxGroup: BFormCheckboxGroup,
        BCheckGroup: BFormCheckboxGroup
      }
    });
  
    // v-b-hover directive
  
    var PROP = '__BV_hover_handler__';
    var MOUSEENTER = 'mouseenter';
    var MOUSELEAVE = 'mouseleave'; // --- Utility methods ---
  
    var createListener = function createListener(handler) {
      var listener = function listener(evt) {
        handler(evt.type === MOUSEENTER, evt);
      };
  
      listener.fn = handler;
      return listener;
    };
  
    var updateListeners = function updateListeners(on, el, listener) {
      eventOnOff(on, el, MOUSEENTER, listener, EVENT_OPTIONS_NO_CAPTURE);
      eventOnOff(on, el, MOUSELEAVE, listener, EVENT_OPTIONS_NO_CAPTURE);
    }; // --- Directive bind/unbind/update handler ---
  
  
    var directive = function directive(el, _ref) {
      var _ref$value = _ref.value,
          handler = _ref$value === void 0 ? null : _ref$value;
  
      if (isBrowser) {
        var listener = el[PROP];
        var hasListener = isFunction(listener);
        var handlerChanged = !(hasListener && listener.fn === handler);
  
        if (hasListener && handlerChanged) {
          updateListeners(false, el, listener);
          delete el[PROP];
        }
  
        if (isFunction(handler) && handlerChanged) {
          el[PROP] = createListener(handler);
          updateListeners(true, el, el[PROP]);
        }
      }
    }; // VBHover directive
  
  
    var VBHover = {
      bind: directive,
      componentUpdated: directive,
      unbind: function unbind(el) {
        directive(el, {
          value: null
        });
      }
    };
  
    var dropdownProps = commonProps; // @vue/component
  
    var BVFormBtnLabelControl = /*#__PURE__*/Vue.extend({
      name: 'BVFormBtnLabelControl',
      directives: {
        BHover: VBHover
      },
      mixins: [idMixin, normalizeSlotMixin, dropdownMixin],
      props: {
        value: {
          // This is the value placed on the hidden input
          type: String,
          default: ''
        },
        formattedValue: {
          // This is the value shown in the label
          // Defaults back to `value`
          type: String // default: null
  
        },
        placeholder: {
          // This is the value placed on the hidden input when no value selected
          type: String // default: null
  
        },
        labelSelected: {
          // Value placed in sr-only span inside label when value is present
          type: String // default: null
  
        },
        state: {
          // Tri-state prop: `true`, `false`, or `null`
          type: Boolean,
          // We must explicitly default to `null` here otherwise
          // Vue coerces `undefined` into Boolean `false`
          default: null
        },
        size: {
          type: String // default: null
  
        },
        name: {
          type: String // default: null
  
        },
        form: {
          type: String // default: null
  
        },
        disabled: {
          type: Boolean,
          default: false
        },
        readonly: {
          type: Boolean,
          default: false
        },
        required: {
          type: Boolean,
          default: false
        },
        lang: {
          type: String // default: null
  
        },
        rtl: {
          // Tri-state prop: `true`, `false` or `null`
          type: Boolean,
          // We must explicitly default to `null` here otherwise
          // Vue coerces `undefined` into Boolean `false`
          default: null
        },
        menuClass: {
          // Extra classes to apply to the `dropdown-menu` div
          type: [String, Array, Object] // default: null
  
        }
      },
      data: function data() {
        return {
          isHovered: false,
          hasFocus: false
        };
      },
      computed: {
        idButton: function idButton() {
          return this.safeId();
        },
        idLabel: function idLabel() {
          return this.safeId('_value_');
        },
        idMenu: function idMenu() {
          return this.safeId('_dialog_');
        },
        idWrapper: function idWrapper() {
          return this.safeId('_outer_');
        },
        computedDir: function computedDir() {
          return this.rtl === true ? 'rtl' : this.rtl === false ? 'ltr' : null;
        }
      },
      methods: {
        focus: function focus() {
          if (!this.disabled) {
            try {
              this.$refs.toggle.focus();
            } catch (_unused) {}
          }
        },
        blur: function blur() {
          if (!this.disabled) {
            try {
              this.$refs.toggle.blur();
            } catch (_unused2) {}
          }
        },
        setFocus: function setFocus(evt) {
          this.hasFocus = evt.type === 'focus';
        },
        handleHover: function handleHover(hovered) {
          this.isHovered = hovered;
        },
        stopEvent: function stopEvent(evt)
        /* istanbul ignore next */
        {
          evt.stopPropagation();
        }
      },
      render: function render(h) {
        var _class2, _ref;
  
        var idButton = this.idButton;
        var idLabel = this.idLabel;
        var idMenu = this.idMenu;
        var idWrapper = this.idWrapper;
        var disabled = this.disabled;
        var readonly = this.readonly;
        var required = this.required;
        var isHovered = this.isHovered;
        var hasFocus = this.hasFocus;
        var state = this.state;
        var visible = this.visible;
        var size = this.size;
        var value = toString$1(this.value) || '';
        var labelSelected = this.labelSelected;
        var btnScope = {
          isHovered: isHovered,
          hasFocus: hasFocus,
          state: state,
          opened: visible
        };
        var $button = h('button', {
          ref: 'toggle',
          staticClass: 'btn border-0 h-auto py-0',
          class: _defineProperty({}, "btn-".concat(size), !!size),
          attrs: {
            id: idButton,
            type: 'button',
            disabled: disabled,
            'aria-haspopup': 'dialog',
            'aria-expanded': visible ? 'true' : 'false',
            'aria-invalid': state === false || required && !value ? 'true' : null,
            'aria-required': required ? 'true' : null
          },
          directives: [{
            name: 'b-hover',
            value: this.handleHover
          }],
          on: {
            mousedown: this.onMousedown,
            click: this.toggle,
            keydown: this.toggle,
            // Handle ENTER, SPACE and DOWN
            '!focus': this.setFocus,
            '!blur': this.setFocus
          }
        }, [this.hasNormalizedSlot('button-content') ? this.normalizeSlot('button-content', btnScope) : h(BIconChevronDown, {
          props: {
            scale: 1.25
          }
        })]); // Hidden input
  
        var $hidden = h();
  
        if (this.name && !disabled) {
          $hidden = h('input', {
            attrs: {
              type: 'hidden',
              name: this.name || null,
              form: this.form || null,
              value: value
            }
          });
        } // Dropdown content
  
  
        var $menu = h('div', {
          ref: 'menu',
          staticClass: 'dropdown-menu p-2',
          class: [this.menuClass, {
            show: visible,
            'dropdown-menu-right': this.right
          }],
          attrs: {
            id: idMenu,
            role: 'dialog',
            tabindex: '-1',
            'aria-modal': 'false',
            'aria-labelledby': idLabel
          },
          on: {
            keydown: this.onKeydown // Handle ESC
  
          }
        }, [this.normalizeSlot('default', {
          opened: visible
        })]); // Value label
  
        var $label = h('label', {
          staticClass: 'form-control text-break text-wrap border-0 bg-transparent h-auto pl-1 m-0',
          class: (_class2 = {
            // Mute the text if showing the placeholder
            'text-muted': !value
          }, _defineProperty(_class2, "form-control-".concat(size), !!size), _defineProperty(_class2, 'is-invalid', state === false), _defineProperty(_class2, 'is-valid', state === true), _class2),
          attrs: {
            id: idLabel,
            for: idButton,
            'aria-invalid': state === false || required && !value ? 'true' : null,
            'aria-required': required ? 'true' : null
          },
          directives: [{
            name: 'b-hover',
            value: this.handleHover
          }],
          on: {
            // Disable bubbling of the click event to
            // prevent menu from closing and re-opening
            '!click': this.stopEvent
          }
        }, [value ? this.formattedValue || value : this.placeholder || '', // Add the selected label for screen readers when a value is provided
        value && labelSelected ? h('bdi', {
          staticClass: 'sr-only'
        }, labelSelected) : '']); // Return the custom form control wrapper
  
        return h('div', {
          staticClass: 'b-form-btn-label-control form-control dropdown d-flex p-0 h-auto align-items-stretch',
          class: [this.directionClass, (_ref = {
            show: visible,
            focus: hasFocus
          }, _defineProperty(_ref, "form-control-".concat(size), !!size), _defineProperty(_ref, 'is-valid', state === true), _defineProperty(_ref, 'is-invalid', state === false), _ref)],
          attrs: {
            id: idWrapper,
            role: 'group',
            lang: this.lang || null,
            dir: this.computedDir,
            'aria-disabled': disabled,
            'aria-readonly': readonly && !disabled,
            'aria-labelledby': idLabel,
            'aria-invalid': state === false || required && !value ? 'true' : null,
            'aria-required': required ? 'true' : null
          }
        }, [$button, $hidden, $menu, $label]);
      }
    });
  
    var NAME$d = 'BFormDatepicker'; // Fallback to BCalendar prop if no value found
  
    var getConfigFallback = function getConfigFallback(prop) {
      return getComponentConfig(NAME$d, prop) || getComponentConfig('BCalendar', prop);
    }; // We create our props as a mixin so that we can control
    // where they appear in the props listing reference section
  
  
    var propsMixin = {
      props: _objectSpread2({
        value: {
          type: [String, Date],
          default: null
        },
        valueAsDate: {
          type: Boolean,
          default: false
        },
        resetValue: {
          type: [String, Date],
          default: ''
        },
        placeholder: {
          type: String,
          // Defaults to `labelNoDateSelected` from calendar context
          default: null
        },
        size: {
          type: String,
          default: null
        },
        min: {
          type: [String, Date],
          default: null
        },
        max: {
          type: [String, Date],
          default: null
        },
        disabled: {
          type: Boolean,
          default: false
        },
        readonly: {
          type: Boolean,
          default: false
        },
        required: {
          // If true adds the `aria-required` attribute
          type: Boolean,
          default: false
        },
        name: {
          type: String,
          default: null
        },
        form: {
          type: String,
          default: null
        },
        state: {
          // Tri-state prop: `true`, `false` or `null`
          type: Boolean,
          default: null
        },
        dateDisabledFn: {
          type: Function,
          default: null
        },
        noCloseOnSelect: {
          type: Boolean,
          default: false
        },
        hideHeader: {
          type: Boolean,
          default: false
        },
        locale: {
          type: [String, Array],
          default: null
        },
        startWeekday: {
          // `0` (Sunday), `1` (Monday), ... `6` (Saturday)
          // Day of week to start calendar on
          type: [Number, String],
          default: 0
        },
        direction: {
          type: String,
          default: null
        },
        calendarWidth: {
          // Width of the calendar dropdown
          type: String,
          default: '270px'
        },
        selectedVariant: {
          // Variant color to use for the selected date
          type: String,
          default: 'primary'
        },
        todayVariant: {
          // Variant color to use for today's date (defaults to `variant`)
          type: String,
          default: null
        },
        noHighlightToday: {
          // Disable highlighting today's date
          type: Boolean,
          default: false
        },
        todayButton: {
          type: Boolean,
          default: false
        },
        labelTodayButton: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$d, 'labelTodayButton');
          }
        },
        todayButtonVariant: {
          type: String,
          default: 'outline-primary'
        },
        resetButton: {
          type: Boolean,
          default: false
        },
        labelResetButton: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$d, 'labelResetButton');
          }
        },
        resetButtonVariant: {
          type: String,
          default: 'outline-danger'
        },
        closeButton: {
          type: Boolean,
          default: false
        },
        labelCloseButton: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$d, 'labelCloseButton');
          }
        },
        closeButtonVariant: {
          type: String,
          default: 'outline-secondary'
        },
        // Labels for buttons and keyboard shortcuts
        // These pick BCalendar global config if no BFormDate global config
        labelPrevYear: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelPrevYear');
          }
        },
        labelPrevMonth: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelPrevMonth');
          }
        },
        labelCurrentMonth: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelCurrentMonth');
          }
        },
        labelNextMonth: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelNextMonth');
          }
        },
        labelNextYear: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelNextYear');
          }
        },
        labelToday: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelToday');
          }
        },
        labelSelected: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelSelected');
          }
        },
        labelNoDateSelected: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelNoDateSelected');
          }
        },
        labelCalendar: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelCalendar');
          }
        },
        labelNav: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelNav');
          }
        },
        labelHelp: {
          type: String,
          default: function _default() {
            return getConfigFallback('labelHelp');
          }
        },
        dateFormatOptions: {
          // `Intl.DateTimeFormat` object
          type: Object,
          default: function _default() {
            return {
              year: 'numeric',
              month: 'long',
              day: 'numeric',
              weekday: 'long'
            };
          }
        },
        // Dark mode
        dark: {
          type: Boolean,
          default: false
        },
        // extra dropdown stuff
        menuClass: {
          type: [String, Array, Object],
          default: null
        }
      }, dropdownProps)
    }; // --- BFormDate component ---
    // @vue/component
  
    var BFormDatepicker = /*#__PURE__*/Vue.extend({
      name: NAME$d,
      // The mixins order determines the order of appearance in the props reference section
      mixins: [idMixin, propsMixin],
      model: {
        prop: 'value',
        event: 'input'
      },
      data: function data() {
        return {
          // We always use `YYYY-MM-DD` value internally
          localYMD: formatYMD(this.value) || '',
          // Context data from BCalendar
          localLocale: null,
          isRTL: false,
          formattedValue: '',
          activeYMD: '',
          // If the popup is open
          isVisible: false
        };
      },
      computed: {
        calendarYM: function calendarYM() {
          // Returns the calendar year/month
          // Returns the `YYYY-MM` portion of the active calendar date
          return this.activeYMD.slice(0, -3);
        },
        calendarProps: function calendarProps() {
          // Use self for better minification, as `this` won't
          // minimize and we reference it many times below
          var self = this;
          return {
            hidden: !self.isVisible,
            value: self.localYMD,
            min: self.min,
            max: self.max,
            readonly: self.readonly,
            disabled: self.disabled,
            locale: self.locale,
            startWeekday: self.startWeekday,
            direction: self.direction,
            width: self.calendarWidth,
            dateDisabledFn: self.dateDisabledFn,
            selectedVariant: self.selectedVariant,
            todayVariant: self.todayVariant,
            hideHeader: self.hideHeader,
            labelPrevYear: self.labelPrevYear,
            labelPrevMonth: self.labelPrevMonth,
            labelCurrentMonth: self.labelCurrentMonth,
            labelNextMonth: self.labelNextMonth,
            labelNextYear: self.labelNextYear,
            labelToday: self.labelToday,
            labelSelected: self.labelSelected,
            labelNoDateSelected: self.labelNoDateSelected,
            labelCalendar: self.labelCalendar,
            labelNav: self.labelNav,
            labelHelp: self.labelHelp,
            dateFormatOptions: self.dateFormatOptions
          };
        },
        computedLang: function computedLang() {
          return (this.localLocale || '').replace(/-u-.*$/i, '') || null;
        },
        computedResetValue: function computedResetValue() {
          return formatYMD(this.resetValue) || '';
        }
      },
      watch: {
        value: function value(newVal) {
          this.localYMD = formatYMD(newVal) || '';
        },
        localYMD: function localYMD(newVal) {
          this.$emit('input', this.valueAsDate ? parseYMD(newVal) || null : newVal || '');
        },
        calendarYM: function calendarYM(newVal, oldVal)
        /* istanbul ignore next */
        {
          // Displayed calendar month has changed
          // So possibly the calendar height has changed...
          // We need to update popper computed position
          if (newVal !== oldVal && oldVal) {
            try {
              this.$refs.control.updatePopper();
            } catch (_unused) {}
          }
        }
      },
      methods: {
        // Public methods
        focus: function focus() {
          if (!this.disabled) {
            try {
              this.$refs.control.focus();
            } catch (_unused2) {}
          }
        },
        blur: function blur() {
          if (!this.disabled) {
            try {
              this.$refs.control.blur();
            } catch (_unused3) {}
          }
        },
        // Private methods
        setAndClose: function setAndClose(ymd) {
          var _this = this;
  
          this.localYMD = ymd; // Close calendar popup, unless `noCloseOnSelect`
  
          if (!this.noCloseOnSelect) {
            this.$nextTick(function () {
              _this.$refs.control.hide(true);
            });
          }
        },
        onSelected: function onSelected(ymd) {
          var _this2 = this;
  
          this.$nextTick(function () {
            _this2.setAndClose(ymd);
          });
        },
        onInput: function onInput(ymd) {
          if (this.localYMD !== ymd) {
            this.localYMD = ymd;
          }
        },
        onContext: function onContext(ctx) {
          var activeYMD = ctx.activeYMD,
              isRTL = ctx.isRTL,
              locale = ctx.locale,
              selectedYMD = ctx.selectedYMD,
              selectedFormatted = ctx.selectedFormatted;
          this.isRTL = isRTL;
          this.localLocale = locale;
          this.formattedValue = selectedFormatted;
          this.localYMD = selectedYMD;
          this.activeYMD = activeYMD; // Re-emit the context event
  
          this.$emit('context', ctx);
        },
        onTodayButton: function onTodayButton() {
          this.setAndClose(formatYMD(createDate()));
        },
        onResetButton: function onResetButton() {
          this.setAndClose(this.computedResetValue);
        },
        onCloseButton: function onCloseButton() {
          this.$refs.control.hide(true);
        },
        // Menu handlers
        onShow: function onShow() {
          this.isVisible = true;
        },
        onShown: function onShown() {
          var _this3 = this;
  
          this.$nextTick(function () {
            try {
              _this3.$refs.calendar.focus();
            } catch (_unused4) {}
          });
        },
        onHidden: function onHidden() {
          this.isVisible = false;
        },
        // Render helpers
        defaultButtonFn: function defaultButtonFn(_ref) {
          var isHovered = _ref.isHovered,
              hasFocus = _ref.hasFocus;
          return this.$createElement(isHovered || hasFocus ? BIconCalendarFill : BIconCalendar, {
            props: {
              scale: 1.25
            },
            attrs: {
              'aria-hidden': 'true'
            }
          });
        }
      },
      render: function render(h) {
        var localYMD = this.localYMD;
        var disabled = this.disabled;
        var readonly = this.readonly;
        var placeholder = isUndefinedOrNull(this.placeholder) ? this.labelNoDateSelected : this.placeholder; // Optional footer buttons
  
        var $footer = [];
  
        if (this.todayButton) {
          var label = this.labelTodayButton;
          $footer.push(h(BButton, {
            props: {
              size: 'sm',
              disabled: disabled || readonly,
              variant: this.todayButtonVariant
            },
            attrs: {
              'aria-label': label || null
            },
            on: {
              click: this.onTodayButton
            }
          }, label));
        }
  
        if (this.resetButton) {
          var _label = this.labelResetButton;
          $footer.push(h(BButton, {
            props: {
              size: 'sm',
              disabled: disabled || readonly,
              variant: this.resetButtonVariant
            },
            attrs: {
              'aria-label': _label || null
            },
            on: {
              click: this.onResetButton
            }
          }, _label));
        }
  
        if (this.closeButton) {
          var _label2 = this.labelCloseButton;
          $footer.push(h(BButton, {
            props: {
              size: 'sm',
              disabled: disabled,
              variant: this.closeButtonVariant
            },
            attrs: {
              'aria-label': _label2 || null
            },
            on: {
              click: this.onCloseButton
            }
          }, _label2));
        }
  
        if ($footer.length > 0) {
          $footer = [h('div', {
            staticClass: 'b-form-date-controls d-flex flex-wrap',
            class: {
              'justify-content-between': $footer.length > 1,
              'justify-content-end': $footer.length < 2
            }
          }, $footer)];
        }
  
        var $calendar = h(BCalendar, {
          key: 'calendar',
          ref: 'calendar',
          staticClass: 'b-form-date-calendar',
          props: this.calendarProps,
          on: {
            selected: this.onSelected,
            input: this.onInput,
            context: this.onContext
          }
        }, $footer);
        return h(BVFormBtnLabelControl, {
          ref: 'control',
          staticClass: 'b-form-datepicker',
          props: _objectSpread2({}, this.$props, {
            // Overridden / computed props
            id: this.safeId(),
            rtl: this.isRTL,
            lang: this.computedLang,
            value: localYMD || '',
            formattedValue: localYMD ? this.formattedValue : '',
            placeholder: placeholder || '',
            menuClass: [{
              'bg-dark': !!this.dark,
              'text-light': !!this.dark
            }, this.menuClass]
          }),
          on: {
            show: this.onShow,
            shown: this.onShown,
            hidden: this.onHidden
          },
          scopedSlots: {
            'button-content': this.$scopedSlots['button-content'] || this.defaultButtonFn
          }
        }, [$calendar]);
      }
    });
  
    var FormDatepickerPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormDatepicker: BFormDatepicker,
        BDatepicker: BFormDatepicker
      }
    });
  
    // @vue/component
    var formCustomMixin = {
      props: {
        plain: {
          type: Boolean,
          default: false
        }
      },
      computed: {
        custom: function custom() {
          return !this.plain;
        }
      }
    };
  
    var NAME$e = 'BFormFile';
    var VALUE_EMPTY_DEPRECATED_MSG = 'Setting "value"/"v-model" to an empty string for reset is deprecated. Set to "null" instead.'; // @vue/component
  
    var BFormFile = /*#__PURE__*/Vue.extend({
      name: NAME$e,
      mixins: [idMixin, formMixin, formStateMixin, formCustomMixin, normalizeSlotMixin],
      inheritAttrs: false,
      model: {
        prop: 'value',
        event: 'input'
      },
      props: {
        size: {
          type: String,
          default: function _default() {
            return getComponentConfig('BFormControl', 'size');
          }
        },
        value: {
          type: [File, Array],
          default: null,
          validator: function validator(val) {
            /* istanbul ignore next */
            if (val === '') {
              warn(VALUE_EMPTY_DEPRECATED_MSG, NAME$e);
              return true;
            }
  
            return isUndefinedOrNull(val) || isFile(val) || isArray(val) && (val.length === 0 || val.every(isFile));
          }
        },
        accept: {
          type: String,
          default: ''
        },
        // Instruct input to capture from camera
        capture: {
          type: Boolean,
          default: false
        },
        placeholder: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$e, 'placeholder');
          }
        },
        browseText: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$e, 'browseText');
          }
        },
        dropPlaceholder: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$e, 'dropPlaceholder');
          }
        },
        multiple: {
          type: Boolean,
          default: false
        },
        directory: {
          type: Boolean,
          default: false
        },
        noTraverse: {
          type: Boolean,
          default: false
        },
        noDrop: {
          type: Boolean,
          default: false
        },
        fileNameFormatter: {
          type: Function,
          default: null
        }
      },
      data: function data() {
        return {
          selectedFile: null,
          dragging: false,
          hasFocus: false
        };
      },
      computed: {
        selectLabel: function selectLabel() {
          // Draging active
          if (this.dragging && this.dropPlaceholder) {
            return this.dropPlaceholder;
          } // No file chosen
  
  
          if (!this.selectedFile || this.selectedFile.length === 0) {
            return this.placeholder;
          } // Convert selectedFile to an array (if not already one)
  
  
          var files = concat(this.selectedFile).filter(identity);
  
          if (this.hasNormalizedSlot('file-name')) {
            // There is a slot for formatting the files/names
            return [this.normalizeSlot('file-name', {
              files: files,
              names: files.map(function (f) {
                return f.name;
              })
            })];
          } else {
            // Use the user supplied formatter, or the built in one.
            return isFunction(this.fileNameFormatter) ? toString$1(this.fileNameFormatter(files)) : files.map(function (file) {
              return file.name;
            }).join(', ');
          }
        }
      },
      watch: {
        selectedFile: function selectedFile(newVal, oldVal) {
          // The following test is needed when the file input is "reset" or the
          // exact same file(s) are selected to prevent an infinite loop.
          // When in `multiple` mode we need to check for two empty arrays or
          // two arrays with identical files
          if (newVal === oldVal || isArray(newVal) && isArray(oldVal) && newVal.length === oldVal.length && newVal.every(function (v, i) {
            return v === oldVal[i];
          })) {
            return;
          }
  
          if (!newVal && this.multiple) {
            this.$emit('input', []);
          } else {
            this.$emit('input', newVal);
          }
        },
        value: function value(newVal) {
          if (!newVal || isArray(newVal) && newVal.length === 0) {
            this.reset();
          }
        }
      },
      methods: {
        focusHandler: function focusHandler(evt) {
          // Bootstrap v4 doesn't have focus styling for custom file input
          // Firefox has a '[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;
          /* istanbul ignore next: not supported in JSDOM */
  
          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() {
          var files = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  
          if (!files) {
            /* istanbul ignore next: this will probably not happen */
            this.selectedFile = null;
          } else if (this.multiple) {
            // Convert files to array
            var filesArray = [];
  
            for (var i = 0; i < files.length; i++) {
              filesArray.push(files[i]);
            } // Return file(s) as array
  
  
            this.selectedFile = filesArray;
          } else {
            // Return single file object
            this.selectedFile = files[0] || null;
          }
        },
        onReset: function onReset() {
          // Triggered when the parent form (if any) is reset
          this.selectedFile = this.multiple ? [] : null;
        },
        onDragover: function onDragover(evt)
        /* istanbul ignore next: difficult to test in JSDOM */
        {
          evt.preventDefault();
          evt.stopPropagation();
  
          if (this.noDrop || !this.custom) {
            return;
          }
  
          this.dragging = true;
          evt.dataTransfer.dropEffect = 'copy';
        },
        onDragleave: function onDragleave(evt)
        /* istanbul ignore next: difficult to test in JSDOM */
        {
          evt.preventDefault();
          evt.stopPropagation();
          this.dragging = false;
        },
        onDrop: function onDrop(evt)
        /* istanbul ignore next: difficult to test in JSDOM */
        {
          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)
        /* istanbul ignore next: not supported in JSDOM */
        {
          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));
                });
              });
            }
          });
        }
      },
      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: _objectSpread2({}, this.$attrs, {
            type: 'file',
            id: this.safeId(),
            name: this.name,
            disabled: this.disabled,
            required: this.required,
            form: this.form || null,
            capture: this.capture || null,
            accept: this.accept || null,
            multiple: this.multiple,
            webkitdirectory: this.directory,
            'aria-required': this.required ? 'true' : null
          }),
          on: {
            change: this.onFileChange,
            focusin: this.focusHandler,
            focusout: this.focusHandler,
            reset: this.onReset
          }
        });
  
        if (this.plain) {
          return input;
        } // Overlay Labels
  
  
        var label = h('label', {
          staticClass: 'custom-file-label',
          class: [this.dragging ? 'dragging' : null],
          attrs: {
            for: this.safeId(),
            'data-browse': this.browseText || null
          }
        }, this.selectLabel); // Return rendered custom file input
  
        return h('div', {
          staticClass: 'custom-file b-form-file',
          class: [this.stateClass, _defineProperty({}, "b-custom-control-".concat(this.size), this.size)],
          attrs: {
            id: this.safeId('_BV_file_outer_')
          },
          on: {
            dragover: this.onDragover,
            dragleave: this.onDragleave,
            drop: this.onDrop
          }
        }, [input, label]);
      }
    });
  
    var FormFilePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormFile: BFormFile,
        BFile: BFormFile
      }
    });
  
    /**
     * 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
     */
  
    var suffixPropName = function suffixPropName(suffix, str) {
      return str + (suffix ? upperFirst(suffix) : '');
    };
  
    var RX_COL_CLASS = /^col-/; // Generates a prop object with a type of `[Boolean, String, Number]`
  
    var boolStrNum = function boolStrNum() {
      return {
        type: [Boolean, String, Number],
        default: false
      };
    }; // Generates a prop object with a type of `[String, Number]`
  
  
    var strNum = function strNum() {
      return {
        type: [String, Number],
        default: null
      };
    }; // Compute a breakpoint class name
  
  
    var computeBreakpoint = function computeBreakpoint(type, breakpoint, val) {
      var className = type;
  
      if (isUndefinedOrNull(val) || val === false) {
        return undefined;
      }
  
      if (breakpoint) {
        className += "-".concat(breakpoint);
      } // Handling the boolean style prop when accepting [Boolean, String, Number]
      // means Vue will not convert <b-col sm></b-col> 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 lowerCase(className);
      } // .order-md-6
  
  
      className += "-".concat(val);
      return lowerCase(className);
    }; // Memoized function for better performance on generating class names
  
  
    var computeBreakpointClass = memoize(computeBreakpoint); // Cached copy of the breakpoint prop names
  
    var breakpointPropMap = create(null); // Lazy evaled props factory for BCol
  
    var generateProps = function generateProps() {
      // Grab the breakpoints from the cached config (exclude the '' (xs) breakpoint)
      var breakpoints = getBreakpointsUpCached().filter(identity); // Supports classes like: .col-sm, .col-md-6, .col-lg-auto
  
      var breakpointCol = breakpoints.reduce(function (propMap, breakpoint) {
        if (breakpoint) {
          // We filter out the '' breakpoint (xs), as making a prop name ''
          // would not work. The `cols` prop is used for `xs`
          propMap[breakpoint] = boolStrNum();
        }
  
        return propMap;
      }, create(null)); // Supports classes like: .offset-md-1, .offset-lg-12
  
      var breakpointOffset = breakpoints.reduce(function (propMap, breakpoint) {
        propMap[suffixPropName(breakpoint, 'offset')] = strNum();
        return propMap;
      }, create(null)); // Supports classes like: .order-md-1, .order-lg-12
  
      var breakpointOrder = breakpoints.reduce(function (propMap, breakpoint) {
        propMap[suffixPropName(breakpoint, 'order')] = strNum();
        return propMap;
      }, create(null)); // For loop doesn't need to check hasOwnProperty
      // when using an object created from null
  
      breakpointPropMap = assign(create(null), {
        col: keys(breakpointCol),
        offset: keys(breakpointOffset),
        order: keys(breakpointOrder)
      }); // Return the generated props
  
      return _objectSpread2({
        // Generic flexbox .col (xs)
        col: {
          type: Boolean,
          default: false
        },
        // .col-[1-12]|auto  (xs)
        cols: strNum()
      }, breakpointCol, {
        offset: strNum()
      }, breakpointOffset, {
        order: strNum()
      }, breakpointOrder, {
        // Flex alignment
        alignSelf: {
          type: String,
          default: null,
          validator: function validator(str) {
            return arrayIncludes(['auto', 'start', 'end', 'center', 'baseline', 'stretch'], str);
          }
        },
        tag: {
          type: String,
          default: 'div'
        }
      });
    }; // We do not use Vue.extend here as that would evaluate the props
    // immediately, which we do not want to happen
    // @vue/component
  
  
    var BCol = {
      name: 'BCol',
      functional: true,
  
      get props() {
        // Allow props to be lazy evaled on first access and
        // then they become a non-getter afterwards.
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters
        delete this.props; // eslint-disable-next-line no-return-assign
  
        return this.props = generateProps();
      },
  
      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++) {
            // computeBreakpoint(col, colSm => Sm, value=[String, Number, Boolean])
            var c = computeBreakpointClass(type, _keys[i].replace(type, ''), props[_keys[i]]); // If a class is returned, push it onto the array.
  
            if (c) {
              classList.push(c);
            }
          }
        }
  
        var hasColClasses = classList.some(function (className) {
          return RX_COL_CLASS.test(className);
        });
        classList.push((_classList$push = {
          // Default to .col if no other col-{bp}-* classes generated nor `cols` specified.
          col: props.col || !hasColClasses && !props.cols
        }, _defineProperty(_classList$push, "col-".concat(props.cols), props.cols), _defineProperty(_classList$push, "offset-".concat(props.offset), props.offset), _defineProperty(_classList$push, "order-".concat(props.order), props.order), _defineProperty(_classList$push, "align-self-".concat(props.alignSelf), props.alignSelf), _classList$push));
        return h(props.tag, a(data, {
          class: classList
        }), children);
      }
    };
  
    var NAME$f = 'BFormGroup'; // Selector for finding first input in the form-group
  
    var SELECTOR$1 = 'input:not([disabled]),textarea:not([disabled]),select:not([disabled])'; // Render helper functions (here rather than polluting the instance with more methods)
  
    var renderInvalidFeedback = function renderInvalidFeedback(h, ctx) {
      var content = ctx.normalizeSlot('invalid-feedback') || ctx.invalidFeedback;
      var invalidFeedback = h();
  
      if (content) {
        invalidFeedback = h(BFormInvalidFeedback, {
          props: {
            id: ctx.invalidFeedbackId,
            // If state is explicitly false, always show the feedback
            state: ctx.computedState,
            tooltip: ctx.tooltip,
            ariaLive: ctx.feedbackAriaLive,
            role: ctx.feedbackAriaLive ? 'alert' : null
          },
          attrs: {
            tabindex: content ? '-1' : null
          }
        }, [content]);
      }
  
      return invalidFeedback;
    };
  
    var renderValidFeedback = function renderValidFeedback(h, ctx) {
      var content = ctx.normalizeSlot('valid-feedback') || ctx.validFeedback;
      var validFeedback = h();
  
      if (content) {
        validFeedback = h(BFormValidFeedback, {
          props: {
            id: ctx.validFeedbackId,
            // If state is explicitly true, always show the feedback
            state: ctx.computedState,
            tooltip: ctx.tooltip,
            ariaLive: ctx.feedbackAriaLive,
            role: ctx.feedbackAriaLive ? 'alert' : null
          },
          attrs: {
            tabindex: content ? '-1' : null
          }
        }, [content]);
      }
  
      return validFeedback;
    };
  
    var renderHelpText = function renderHelpText(h, ctx) {
      // Form help text (description)
      var content = ctx.normalizeSlot('description') || ctx.description;
      var description = h();
  
      if (content) {
        description = h(BFormText, {
          attrs: {
            id: ctx.descriptionId,
            tabindex: content ? '-1' : null
          }
        }, [content]);
      }
  
      return description;
    };
  
    var renderLabel = function renderLabel(h, ctx) {
      // Render label/legend inside b-col if necessary
      var content = ctx.normalizeSlot('label') || ctx.label;
      var labelFor = ctx.labelFor;
      var isLegend = !labelFor;
      var isHorizontal = ctx.isHorizontal;
      var labelTag = isLegend ? 'legend' : 'label';
  
      if (!content && !isHorizontal) {
        return h();
      } else if (ctx.labelSrOnly) {
        var label = h();
  
        if (content) {
          label = h(labelTag, {
            class: 'sr-only',
            attrs: {
              id: ctx.labelId,
              for: labelFor || null
            }
          }, [content]);
        }
  
        return h(isHorizontal ? BCol : 'div', {
          props: isHorizontal ? ctx.labelColProps : {}
        }, [label]);
      } else {
        return h(isHorizontal ? BCol : labelTag, {
          on: isLegend ? {
            click: ctx.legendClick
          } : {},
          props: isHorizontal ? _objectSpread2({
            tag: labelTag
          }, ctx.labelColProps) : {},
          attrs: {
            id: ctx.labelId,
            for: labelFor || null,
            // We add a tab index to legend so that screen readers
            // will properly read the aria-labelledby in IE.
            tabindex: isLegend ? '-1' : null
          },
          class: [// Hide the focus ring on the legend
          isLegend ? 'bv-no-focus-ring' : '', // When horizontal or if a legend is rendered, add col-form-label
          // for correct sizing as Bootstrap has inconsistent font styling
          // for legend in non-horizontal form-groups.
          // See: https://github.com/twbs/bootstrap/issues/27805
          isHorizontal || isLegend ? 'col-form-label' : '', // Emulate label padding top of 0 on legend when not horizontal
          !isHorizontal && isLegend ? 'pt-0' : '', // If not horizontal and not a legend, we add d-block to label
          // so that label-align works
          !isHorizontal && !isLegend ? 'd-block' : '', ctx.labelSize ? "col-form-label-".concat(ctx.labelSize) : '', ctx.labelAlignClasses, ctx.labelClass]
        }, [content]);
      }
    }; // -- BFormGroup Prop factory -- used for lazy generation of props
    // Memoize this function to return cached values to
    // save time in computed functions
  
  
    var makePropName = memoize(function () {
      var breakpoint = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
      var prefix = arguments.length > 1 ? arguments[1] : undefined;
      return "".concat(prefix).concat(upperFirst(breakpoint));
    }); // BFormGroup prop generator for lazy generation of props
  
    var generateProps$1 = function generateProps() {
      var BREAKPOINTS = getBreakpointsUpCached(); // Generate the labelCol breakpoint props
  
      var bpLabelColProps = BREAKPOINTS.reduce(function (props, breakpoint) {
        // i.e. label-cols, label-cols-sm, label-cols-md, ...
        props[makePropName(breakpoint, 'labelCols')] = {
          type: [Number, String, Boolean],
          default: breakpoint ? false : null
        };
        return props;
      }, create(null)); // Generate the labelAlign breakpoint props
  
      var bpLabelAlignProps = BREAKPOINTS.reduce(function (props, breakpoint) {
        // label-align, label-align-sm, label-align-md, ...
        props[makePropName(breakpoint, 'labelAlign')] = {
          type: String,
          // left, right, center
          default: null
        };
        return props;
      }, create(null));
      return _objectSpread2({
        label: {
          type: String,
          default: null
        },
        labelFor: {
          type: String,
          default: null
        },
        labelSize: {
          type: String,
          default: null
        },
        labelSrOnly: {
          type: Boolean,
          default: false
        }
      }, bpLabelColProps, {}, bpLabelAlignProps, {
        labelClass: {
          type: [String, Array, Object],
          default: null
        },
        description: {
          type: String,
          default: null
        },
        invalidFeedback: {
          type: String,
          default: null
        },
        validFeedback: {
          type: String,
          default: null
        },
        tooltip: {
          // Enable tooltip style feedback
          type: Boolean,
          default: false
        },
        feedbackAriaLive: {
          type: String,
          default: 'assertive'
        },
        validated: {
          type: Boolean,
          default: false
        },
        disabled: {
          type: Boolean,
          default: false
        }
      });
    }; // We do not use Vue.extend here as that would evaluate the props
    // immediately, which we do not want to happen
    // @vue/component
  
  
    var BFormGroup = {
      name: NAME$f,
      mixins: [idMixin, formStateMixin, normalizeSlotMixin],
  
      get props() {
        // Allow props to be lazy evaled on first access and
        // then they become a non-getter afterwards.
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters
        delete this.props; // eslint-disable-next-line no-return-assign
  
        return this.props = generateProps$1();
      },
  
      computed: {
        labelColProps: function labelColProps() {
          var _this = this;
  
          var props = {};
          getBreakpointsUpCached().forEach(function (breakpoint) {
            // Grab the value if the label column breakpoint prop
            var propVal = _this[makePropName(breakpoint, 'labelCols')]; // Handle case where the prop's value is an empty string,
            // which represents true
  
  
            propVal = propVal === '' ? true : propVal || false;
  
            if (!isBoolean(propVal) && propVal !== 'auto') {
              // Convert to column size to number
              propVal = parseInt(propVal, 10) || 0; // Ensure column size is greater than 0
  
              propVal = propVal > 0 ? propVal : false;
            }
  
            if (propVal) {
              // Add the prop to the list of props to give to b-col
              // If breakpoint is '' (labelCols=true), then we use the
              // col prop to make equal width at xs
              var bColPropName = breakpoint || (isBoolean(propVal) ? 'col' : 'cols'); // Add it to the props
  
              props[bColPropName] = propVal;
            }
          });
          return props;
        },
        labelAlignClasses: function labelAlignClasses() {
          var _this2 = this;
  
          var classes = [];
          getBreakpointsUpCached().forEach(function (breakpoint) {
            // Assemble the label column breakpoint align classes
            var propVal = _this2[makePropName(breakpoint, 'labelAlign')] || null;
  
            if (propVal) {
              var className = breakpoint ? "text-".concat(breakpoint, "-").concat(propVal) : "text-".concat(propVal);
              classes.push(className);
            }
          });
          return classes;
        },
        isHorizontal: function isHorizontal() {
          // Determine if the resultant form-group will be rendered
          // horizontal (meaning it has label-col breakpoints)
          return keys(this.labelColProps).length > 0;
        },
        labelId: function labelId() {
          return this.hasNormalizedSlot('label') || this.label ? this.safeId('_BV_label_') : null;
        },
        descriptionId: function descriptionId() {
          return this.hasNormalizedSlot('description') || this.description ? this.safeId('_BV_description_') : null;
        },
        hasInvalidFeedback: function hasInvalidFeedback() {
          // Used for computing aria-describedby
          return this.computedState === false && (this.hasNormalizedSlot('invalid-feedback') || this.invalidFeedback);
        },
        invalidFeedbackId: function invalidFeedbackId() {
          return this.hasInvalidFeedback ? this.safeId('_BV_feedback_invalid_') : null;
        },
        hasValidFeedback: function hasValidFeedback() {
          // Used for computing aria-describedby
          return this.computedState === true && (this.hasNormalizedSlot('valid-feedback') || this.validFeedback);
        },
        validFeedbackId: function validFeedbackId() {
          return this.hasValidFeedback ? this.safeId('_BV_feedback_valid_') : null;
        },
        describedByIds: function describedByIds() {
          // Screen readers will read out any content linked to by aria-describedby
          // even if the content is hidden with `display: none;`, hence we only include
          // feedback IDs if the form-group's state is explicitly valid or invalid.
          return [this.descriptionId, this.invalidFeedbackId, this.validFeedbackId].filter(Boolean).join(' ') || null;
        }
      },
      watch: {
        describedByIds: function describedByIds(add, remove) {
          if (add !== remove) {
            this.setInputDescribedBy(add, remove);
          }
        }
      },
      mounted: function mounted() {
        var _this3 = this;
  
        this.$nextTick(function () {
          // Set the aria-describedby IDs on the input specified by label-for
          // We do this in a nextTick to ensure the children have finished rendering
          _this3.setInputDescribedBy(_this3.describedByIds);
        });
      },
      methods: {
        legendClick: function legendClick(evt) {
          if (this.labelFor) {
            // Don't do anything if labelFor is set
  
            /* istanbul ignore next: clicking a label will focus the input, so no need to test */
            return;
          }
  
          var tagName = evt.target ? evt.target.tagName : '';
  
          if (/^(input|select|textarea|label|button|a)$/i.test(tagName)) {
            // If clicked an interactive element inside legend,
            // we just let the default happen
  
            /* istanbul ignore next */
            return;
          }
  
          var inputs = selectAll(SELECTOR$1, this.$refs.content).filter(isVisible);
  
          if (inputs && inputs.length === 1 && inputs[0].focus) {
            // if only a single input, focus it, emulating label behaviour
            try {
              inputs[0].focus();
            } catch (_unused) {}
          }
        },
        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.
          // Preserves any aria-describedby value(s) user may have on input.
          if (this.labelFor && isBrowser) {
            var input = select("#".concat(this.labelFor), this.$refs.content);
  
            if (input) {
              var adb = 'aria-describedby';
              var ids = (getAttr(input, adb) || '').split(/\s+/);
              add = (add || '').split(/\s+/);
              remove = (remove || '').split(/\s+/); // Update ID list, preserving any original IDs
              // and ensuring the ID's are unique
  
              ids = ids.filter(function (id) {
                return !arrayIncludes(remove, id);
              }).concat(add).filter(Boolean);
              ids = keys(ids.reduce(function (memo, id) {
                return _objectSpread2({}, memo, _defineProperty({}, id, true));
              }, {})).join(' ').trim();
  
              if (ids) {
                setAttr(input, adb, ids);
              } else {
                // No IDs, so remove the attribute
                removeAttr(input, adb);
              }
            }
          }
        }
      },
      render: function render(h) {
        var isFieldset = !this.labelFor;
        var isHorizontal = this.isHorizontal; // Generate the label
  
        var label = renderLabel(h, this); // Generate the content
  
        var content = h(isHorizontal ? BCol : 'div', {
          ref: 'content',
          // Hide focus ring
          staticClass: 'bv-no-focus-ring',
          attrs: {
            tabindex: isFieldset ? '-1' : null,
            role: isFieldset ? 'group' : null
          }
        }, [this.normalizeSlot('default') || h(), renderInvalidFeedback(h, this), renderValidFeedback(h, this), renderHelpText(h, this)]); // Create the form-group
  
        var data = {
          staticClass: 'form-group',
          class: [this.validated ? 'was-validated' : null, this.stateClass],
          attrs: {
            id: this.safeId(),
            disabled: isFieldset ? this.disabled : null,
            role: isFieldset ? null : 'group',
            'aria-invalid': this.computedState === false ? 'true' : null,
            // Only apply aria-labelledby if we are a horizontal fieldset
            // as the legend is no longer a direct child of fieldset
            'aria-labelledby': isFieldset && isHorizontal ? this.labelId : null,
            // Only apply aria-describedby IDs if we are a fieldset
            // as the input will have the IDs when not a fieldset
            'aria-describedby': isFieldset ? this.describedByIds : null
          }
        }; // Return it wrapped in a form-group
        // Note: Fieldsets do not support adding `row` or `form-row` directly
        // to them due to browser specific render issues, so we move the `form-row`
        // to an inner wrapper div when horizontal and using a fieldset
  
        return h(isFieldset ? 'fieldset' : isHorizontal ? BFormRow : 'div', data, isHorizontal && isFieldset ? [h(BFormRow, [label, content])] : [label, content]);
      }
    };
  
    var FormGroupPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormGroup: BFormGroup,
        BFormFieldset: BFormGroup
      }
    });
  
    var formTextMixin = {
      model: {
        prop: 'value',
        event: 'update'
      },
      props: {
        value: {
          type: [String, Number],
          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
        },
        formatter: {
          type: Function,
          default: null
        },
        lazyFormatter: {
          type: Boolean,
          default: false
        },
        trim: {
          type: Boolean,
          default: false
        },
        number: {
          type: Boolean,
          default: false
        },
        lazy: {
          // Only update the `v-model` on blur/change events
          type: Boolean,
          default: false
        },
        debounce: {
          // Debounce timout (in ms). Not applicable with `lazy` prop
          type: [Number, String],
          default: 0
        }
      },
      data: function data() {
        return {
          localValue: toString$1(this.value),
          vModelValue: this.value
        };
      },
      computed: {
        computedClass: function computedClass() {
          return [{
            // Range input needs class `custom-range`
            'custom-range': this.type === 'range',
            // `plaintext` not supported by `type="range"` or `type="color"`
            'form-control-plaintext': this.plaintext && this.type !== 'range' && this.type !== 'color',
            // `form-control` not used by `type="range"` or `plaintext`
            // Always used by `type="color"`
            'form-control': !this.plaintext && this.type !== 'range' || this.type === 'color'
          }, 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 the string 'true')
  
  
          return this.ariaInvalid;
        },
        computedDebounce: function computedDebounce() {
          // Ensure we have a positive number equal to or greater than 0
          return Math.max(toInteger(this.debounce) || 0, 0);
        },
        hasFormatter: function hasFormatter() {
          return isFunction(this.formatter);
        }
      },
      watch: {
        value: function value(newVal) {
          var stringifyValue = toString$1(newVal);
  
          if (stringifyValue !== this.localValue && newVal !== this.vModelValue) {
            // Clear any pending debounce timeout, as we are overwriting the user input
            this.clearDebounce(); // Update the local values
  
            this.localValue = stringifyValue;
            this.vModelValue = newVal;
          }
        }
      },
      mounted: function mounted() {
        // Create non-reactive property and set up destroy handler
        this.$_inputDebounceTimer = null;
        this.$on('hook:beforeDestroy', this.clearDebounce); // Preset the internal state
  
        var value = this.value;
        var stringifyValue = toString$1(value);
        /* istanbul ignore next */
  
        if (stringifyValue !== this.localValue && value !== this.vModelValue) {
          this.localValue = stringifyValue;
          this.vModelValue = value;
        }
      },
      methods: {
        clearDebounce: function clearDebounce() {
          clearTimeout(this.$_inputDebounceTimer);
          this.$_inputDebounceTimer = null;
        },
        formatValue: function formatValue(value, evt) {
          var force = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
          value = toString$1(value);
  
          if (this.hasFormatter && (!this.lazyFormatter || force)) {
            value = this.formatter(value, evt);
          }
  
          return value;
        },
        modifyValue: function modifyValue(value) {
          // Emulate `.trim` modifier behaviour
          if (this.trim) {
            value = value.trim();
          } // Emulate `.number` modifier behaviour
  
  
          if (this.number) {
            var number = toFloat(value);
            value = isNaN(number) ? value : number;
          }
  
          return value;
        },
        updateValue: function updateValue(value) {
          var _this = this;
  
          var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
          var lazy = this.lazy;
  
          if (lazy && !force) {
            return;
          }
  
          value = this.modifyValue(value);
  
          if (value !== this.vModelValue) {
            this.clearDebounce();
  
            var doUpdate = function doUpdate() {
              _this.vModelValue = value;
  
              _this.$emit('update', value);
            };
  
            var debounce = this.computedDebounce; // Only debounce the value update when a value greater than `0`
            // is set and we are not in lazy mode or this is a forced update
  
            if (debounce > 0 && !lazy && !force) {
              this.$_inputDebounceTimer = setTimeout(doUpdate, debounce);
            } else {
              // Immediately update the v-model
              doUpdate();
            }
          } else if (this.hasFormatter) {
            // When the `vModelValue` hasn't changed but the actual input value
            // is out of sync, make sure to change it to the given one
            // Usually caused by browser autocomplete and how it triggers the
            // change or input event, or depending on the formatter function
            // https://github.com/bootstrap-vue/bootstrap-vue/issues/2657
            // https://github.com/bootstrap-vue/bootstrap-vue/issues/3498
  
            /* istanbul ignore next: hard to test */
            var $input = this.$refs.input;
            /* istanbul ignore if: hard to test out of sync value */
  
            if ($input && value !== $input.value) {
              $input.value = value;
            }
          }
        },
        onInput: function onInput(evt) {
          // `evt.target.composing` is set by Vue
          // https://github.com/vuejs/vue/blob/dev/src/platforms/web/runtime/directives/model.js
          // TODO: Is this needed now with the latest Vue?
  
          /* istanbul ignore if: hard to test composition events */
          if (evt.target.composing) {
            return;
          }
  
          var value = evt.target.value;
          var formattedValue = this.formatValue(value, evt); // Exit when the `formatter` function strictly returned `false`
          // or prevented the input event
  
          /* istanbul ignore next */
  
          if (formattedValue === false || evt.defaultPrevented) {
            evt.preventDefault();
            return;
          }
  
          this.localValue = formattedValue;
          this.updateValue(formattedValue);
          this.$emit('input', formattedValue);
        },
        onChange: function onChange(evt) {
          var value = evt.target.value;
          var formattedValue = this.formatValue(value, evt); // Exit when the `formatter` function strictly returned `false`
          // or prevented the input event
  
          /* istanbul ignore next */
  
          if (formattedValue === false || evt.defaultPrevented) {
            evt.preventDefault();
            return;
          }
  
          this.localValue = formattedValue;
          this.updateValue(formattedValue, true);
          this.$emit('change', formattedValue);
        },
        onBlur: function onBlur(evt) {
          // Apply the `localValue` on blur to prevent cursor jumps
          // on mobile browsers (e.g. caused by autocomplete)
          var value = evt.target.value;
          var formattedValue = this.formatValue(value, evt, true);
  
          if (formattedValue !== false) {
            // We need to use the modified value here to apply the
            // `.trim` and `.number` modifiers properly
            this.localValue = toString$1(this.modifyValue(formattedValue)); // We pass the formatted value here since the `updateValue` method
            // handles the modifiers itself
  
            this.updateValue(formattedValue, true);
          } // Emit native blur event
  
  
          this.$emit('blur', evt);
        },
        focus: function focus() {
          // For external handler that may want a focus method
          if (!this.disabled) {
            this.$el.focus();
          }
        },
        blur: function blur() {
          // For external handler that may want a blur method
          if (!this.disabled) {
            this.$el.blur();
          }
        }
      }
    };
  
    // @vue/component
    var formSelectionMixin = {
      computed: {
        selectionStart: {
          // Expose selectionStart for formatters, etc
          cache: false,
          get: function get()
          /* istanbul ignore next */
          {
            return this.$refs.input.selectionStart;
          },
          set: function set(val)
          /* istanbul ignore next */
          {
            this.$refs.input.selectionStart = val;
          }
        },
        selectionEnd: {
          // Expose selectionEnd for formatters, etc
          cache: false,
          get: function get()
          /* istanbul ignore next */
          {
            return this.$refs.input.selectionEnd;
          },
          set: function set(val)
          /* istanbul ignore next */
          {
            this.$refs.input.selectionEnd = val;
          }
        },
        selectionDirection: {
          // Expose selectionDirection for formatters, etc
          cache: false,
          get: function get()
          /* istanbul ignore next */
          {
            return this.$refs.input.selectionDirection;
          },
          set: function set(val)
          /* istanbul ignore next */
          {
            this.$refs.input.selectionDirection = val;
          }
        }
      },
      methods: {
        select: function select()
        /* istanbul ignore next */
        {
          var _this$$refs$input;
  
          // For external handler that may want a select() method
          (_this$$refs$input = this.$refs.input).select.apply(_this$$refs$input, arguments);
        },
        setSelectionRange: function setSelectionRange()
        /* istanbul ignore next */
        {
          var _this$$refs$input2;
  
          // For external handler that may want a setSelectionRange(a,b,c) method
          (_this$$refs$input2 = this.$refs.input).setSelectionRange.apply(_this$$refs$input2, arguments);
        },
        setRangeText: function setRangeText()
        /* istanbul ignore next */
        {
          var _this$$refs$input3;
  
          // For external handler that may want a setRangeText(a,b,c) method
          (_this$$refs$input3 = this.$refs.input).setRangeText.apply(_this$$refs$input3, arguments);
        }
      }
    };
  
    // @vue/component
    var formValidityMixin = {
      computed: {
        validity: {
          // Expose validity property
          cache: false,
          get: function get()
          /* istanbul ignore next */
          {
            return this.$refs.input.validity;
          }
        },
        validationMessage: {
          // Expose validationMessage property
          cache: false,
          get: function get()
          /* istanbul ignore next */
          {
            return this.$refs.input.validationMessage;
          }
        },
        willValidate: {
          // Expose willValidate property
          cache: false,
          get: function get()
          /* istanbul ignore next */
          {
            return this.$refs.input.willValidate;
          }
        }
      },
      methods: {
        setCustomValidity: function setCustomValidity()
        /* istanbul ignore next */
        {
          var _this$$refs$input;
  
          // For external handler that may want a setCustomValidity(...) method
          return (_this$$refs$input = this.$refs.input).setCustomValidity.apply(_this$$refs$input, arguments);
        },
        checkValidity: function checkValidity()
        /* istanbul ignore next */
        {
          var _this$$refs$input2;
  
          // For external handler that may want a checkValidity(...) method
          return (_this$$refs$input2 = this.$refs.input).checkValidity.apply(_this$$refs$input2, arguments);
        },
        reportValidity: function reportValidity()
        /* istanbul ignore next */
        {
          var _this$$refs$input3;
  
          // For external handler that may want a reportValidity(...) method
          return (_this$$refs$input3 = this.$refs.input).reportValidity.apply(_this$$refs$input3, arguments);
        }
      }
    };
  
    var TYPES = ['text', 'password', 'email', 'number', 'url', 'tel', 'search', 'range', 'color', 'date', 'time', 'datetime', 'datetime-local', 'month', 'week']; // @vue/component
  
    var BFormInput = /*#__PURE__*/Vue.extend({
      name: 'BFormInput',
      mixins: [idMixin, formMixin, formSizeMixin, formStateMixin, formTextMixin, formSelectionMixin, formValidityMixin],
      props: {
        // value prop defined in form-text mixin
        // value: { },
        type: {
          type: String,
          default: 'text',
          validator: function validator(type) {
            return arrayIncludes(TYPES, type);
          }
        },
        noWheel: {
          // Disable mousewheel to prevent wheel from changing values (i.e. number/date).
          type: Boolean,
          default: false
        },
        min: {
          type: [String, Number],
          default: null
        },
        max: {
          type: [String, Number],
          default: null
        },
        step: {
          type: [String, Number],
          default: null
        },
        list: {
          type: String,
          default: null
        }
      },
      computed: {
        localType: function localType() {
          // We only allow certain types
          return arrayIncludes(TYPES, this.type) ? this.type : 'text';
        }
      },
      watch: {
        noWheel: function noWheel(newVal) {
          this.setWheelStopper(newVal);
        }
      },
      mounted: function mounted() {
        this.setWheelStopper(this.noWheel);
      },
      deactivated: function deactivated() {
        // Turn off listeners when keep-alive component deactivated
  
        /* istanbul ignore next */
        this.setWheelStopper(false);
      },
      activated: function activated() {
        // Turn on listeners (if no-wheel) when keep-alive component activated
  
        /* istanbul ignore next */
        this.setWheelStopper(this.noWheel);
      },
      beforeDestroy: function beforeDestroy() {
        /* istanbul ignore next */
        this.setWheelStopper(false);
      },
      methods: {
        setWheelStopper: function setWheelStopper(on) {
          var input = this.$el; // We use native events, so that we don't interfere with propagation
  
          eventOnOff(on, input, 'focus', this.onWheelFocus);
          eventOnOff(on, input, 'blur', this.onWheelBlur);
  
          if (!on) {
            eventOff(document, 'wheel', this.stopWheel);
          }
        },
        onWheelFocus: function onWheelFocus() {
          eventOn(document, 'wheel', this.stopWheel);
        },
        onWheelBlur: function onWheelBlur() {
          eventOff(document, 'wheel', this.stopWheel);
        },
        stopWheel: function stopWheel(evt) {
          evt.preventDefault();
          this.$el.blur();
        }
      },
      render: function render(h) {
        var self = this;
        return h('input', {
          ref: 'input',
          class: self.computedClass,
          directives: [{
            name: 'model',
            rawName: 'v-model',
            value: self.localValue,
            expression: 'localValue'
          }],
          attrs: {
            id: self.safeId(),
            name: self.name,
            form: self.form || null,
            type: self.localType,
            disabled: self.disabled,
            placeholder: self.placeholder,
            required: self.required,
            autocomplete: self.autocomplete || null,
            readonly: self.readonly || self.plaintext,
            min: self.min,
            max: self.max,
            step: self.step,
            list: self.localType !== 'password' ? self.list : null,
            'aria-required': self.required ? 'true' : null,
            'aria-invalid': self.computedAriaInvalid
          },
          domProps: {
            value: self.localValue
          },
          on: _objectSpread2({}, self.$listeners, {
            input: self.onInput,
            change: self.onChange,
            blur: self.onBlur
          })
        });
      }
    });
  
    var FormInputPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormInput: BFormInput,
        BInput: BFormInput
      }
    });
  
    var props$w = {
      checked: {
        // type: [String, Number, Boolean, Object],
        default: null
      }
    }; // @vue/component
  
    var BFormRadioGroup = /*#__PURE__*/Vue.extend({
      name: 'BFormRadioGroup',
      mixins: [idMixin, formMixin, formRadioCheckGroupMixin, // Includes render function
      formOptionsMixin, formSizeMixin, formStateMixin],
      provide: function provide() {
        return {
          bvRadioGroup: this
        };
      },
      props: props$w,
      data: function data() {
        return {
          localChecked: this.checked
        };
      },
      computed: {
        isRadioGroup: function isRadioGroup() {
          return true;
        }
      }
    });
  
    var FormRadioPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormRadio: BFormRadio,
        BRadio: BFormRadio,
        BFormRadioGroup: BFormRadioGroup,
        BRadioGroup: BFormRadioGroup
      }
    });
  
    var optionsMixin = {
      mixins: [formOptionsMixin],
      props: {
        labelField: {
          type: String,
          default: 'label'
        },
        optionsField: {
          type: String,
          default: 'options'
        }
      },
      methods: {
        normalizeOption: function normalizeOption(option) {
          var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  
          // When the option is an object, normalize it
          if (isPlainObject(option)) {
            var value = get(option, this.valueField);
            var text = get(option, this.textField);
            var options = get(option, this.optionsField); // When it has options, create an `<optgroup>` object
  
            if (isArray(options)) {
              return {
                label: String(get(option, this.labelField) || text),
                options: options
              };
            } // Otherwise create an `<option>` object
  
  
            return {
              value: isUndefined(value) ? key || text : value,
              text: String(isUndefined(text) ? key : text),
              html: get(option, this.htmlField),
              disabled: Boolean(get(option, this.disabledField))
            };
          } // Otherwise create an `<option>` object from the given value
  
  
          return {
            value: key || option,
            text: String(option),
            disabled: false
          };
        }
      }
    };
  
    var NAME$g = 'BFormSelectOption';
    var props$x = {
      value: {
        // type: [String, Number, Boolean, Object],
        required: true
      },
      disabled: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BFormSelectOption = /*#__PURE__*/Vue.extend({
      name: NAME$g,
      functional: true,
      props: props$x,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var value = props.value,
            disabled = props.disabled;
        return h('option', a(data, {
          attrs: {
            disabled: disabled
          },
          domProps: {
            value: value
          }
        }), children);
      }
    });
  
    var BFormSelectOptionGroup = /*#__PURE__*/Vue.extend({
      name: 'BFormSelectOptionGroup',
      mixins: [normalizeSlotMixin, formOptionsMixin],
      props: {
        label: {
          type: String,
          required: true
        }
      },
      render: function render(h) {
        return h('optgroup', {
          attrs: {
            label: this.label
          }
        }, [this.normalizeSlot('first'), this.formOptions.map(function (option, index) {
          return h(BFormSelectOption, {
            props: {
              value: option.value,
              disabled: option.disabled
            },
            domProps: htmlOrText(option.html, option.text),
            key: "option_".concat(index, "_opt")
          });
        }), this.normalizeSlot('default')]);
      }
    });
  
    var BFormSelect = /*#__PURE__*/Vue.extend({
      name: 'BFormSelect',
      mixins: [idMixin, normalizeSlotMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin, optionsMixin],
      model: {
        prop: 'value',
        event: 'input'
      },
      props: {
        value: {// type: [Object, Array, String, Number, Boolean],
          // default: undefined
        },
        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
        }
      },
      data: function data() {
        return {
          localValue: this.value
        };
      },
      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 [this.plain ? 'form-control' : 'custom-select', this.size && this.plain ? "form-control-".concat(this.size) : null, this.size && !this.plain ? "custom-select-".concat(this.size) : null, this.stateClass];
        },
        computedAriaInvalid: function computedAriaInvalid() {
          if (this.ariaInvalid === true || this.ariaInvalid === 'true') {
            return 'true';
          }
  
          return this.stateClass === 'is-invalid' ? 'true' : null;
        }
      },
      watch: {
        value: function value(newVal) {
          this.localValue = newVal;
        },
        localValue: function localValue() {
          this.$emit('input', this.localValue);
        }
      },
      methods: {
        focus: function focus() {
          this.$refs.input.focus();
        },
        blur: function blur() {
          this.$refs.input.blur();
        }
      },
      render: function render(h) {
        var _this = this;
  
        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,
            form: this.form || null,
            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.$nextTick(function () {
                _this.$emit('change', _this.localValue);
              });
            }
          }
        }, [this.normalizeSlot('first'), this.formOptions.map(function (option, index) {
          var key = "option_".concat(index, "_opt");
          var options = option.options;
          return isArray(options) ? h(BFormSelectOptionGroup, {
            props: {
              label: option.label,
              options: options
            },
            key: key
          }) : h(BFormSelectOption, {
            props: {
              value: option.value,
              disabled: option.disabled
            },
            domProps: htmlOrText(option.html, option.text),
            key: key
          });
        }), this.normalizeSlot('default')]);
      }
    });
  
    var FormSelectPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormSelect: BFormSelect,
        BFormSelectOption: BFormSelectOption,
        BFormSelectOptionGroup: BFormSelectOptionGroup,
        BSelect: BFormSelect,
        BSelectOption: BFormSelectOption,
        BSelectOptionGroup: BFormSelectOptionGroup
      }
    });
  
    var NAME$h = 'BFormSpinbutton';
    var UP$1 = KEY_CODES.UP,
        DOWN$1 = KEY_CODES.DOWN,
        HOME$1 = KEY_CODES.HOME,
        END$1 = KEY_CODES.END,
        PAGEUP$1 = KEY_CODES.PAGEUP,
        PAGEDOWN$1 = KEY_CODES.PAGEDOWN; // Default for spin button range and step
  
    var DEFAULT_MIN = 1;
    var DEFAULT_MAX = 100;
    var DEFAULT_STEP = 1; // Delay before auto-repeat in ms
  
    var DEFAULT_REPEAT_DELAY = 500; // Repeat interval in ms
  
    var DEFAULT_REPEAT_INTERVAL = 100; // Repeat rate increased after number of repeats
  
    var DEFAULT_REPEAT_THRESHOLD = 10; // Repeat speed multiplier (step multiplier, must be an integer)
  
    var DEFAULT_REPEAT_MULTIPLIER = 4; // --- Helper functions ---
  
    var defaultNumber = function defaultNumber(value) {
      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      value = toFloat(value);
      return isNaN(value) ? defaultValue : value;
    };
  
    var defaultInteger = function defaultInteger(value) {
      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      value = toInteger(value);
      return isNaN(value) ? Math.abs(defaultValue) : value;
    }; // --- BFormSpinbutton ---
    // @vue/component
  
  
    var BFormSpinbutton = /*#__PURE__*/Vue.extend({
      name: NAME$h,
      mixins: [idMixin],
      inheritAttrs: false,
      props: {
        value: {
          // Should this really be String, to match native number inputs?
          type: Number,
          default: null
        },
        min: {
          type: [Number, String],
          default: DEFAULT_MIN
        },
        max: {
          type: [Number, String],
          default: DEFAULT_MAX
        },
        step: {
          type: [Number, String],
          default: DEFAULT_STEP
        },
        wrap: {
          type: Boolean,
          default: false
        },
        formatterFn: {
          type: Function // default: null
  
        },
        size: {
          type: String // default: null
  
        },
        placeholder: {
          type: String,
          default: null
        },
        disabled: {
          type: Boolean,
          default: false
        },
        readonly: {
          type: Boolean,
          default: false
        },
        required: {
          // Only affects the `aria-invalid` attribute
          type: Boolean,
          default: false
        },
        name: {
          type: String // default: null
  
        },
        form: {
          type: String // default: null
  
        },
        state: {
          // Tri-state prop: `true`, `false`, or `null`
          type: Boolean,
          default: null
        },
        inline: {
          type: Boolean,
          default: false
        },
        vertical: {
          type: Boolean,
          default: false
        },
        ariaLabel: {
          type: String,
          default: null
        },
        ariaControls: {
          type: String,
          default: null
        },
        labelDecrement: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$h, 'labelDecrement');
          }
        },
        labelIncrement: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$h, 'labelIncrement');
          }
        },
        locale: {
          type: [String, Array],
          default: null
        },
        repeatDelay: {
          type: [Number, String],
          default: DEFAULT_REPEAT_DELAY
        },
        repeatInterval: {
          type: [Number, String],
          default: DEFAULT_REPEAT_INTERVAL
        },
        repeatThreshold: {
          type: [Number, String],
          default: DEFAULT_REPEAT_THRESHOLD
        },
        repeatStepMultiplier: {
          type: [Number, String],
          default: DEFAULT_REPEAT_MULTIPLIER
        }
      },
      data: function data() {
        return {
          localValue: defaultNumber(this.value),
          hasFocus: false
        };
      },
      computed: {
        computedStep: function computedStep() {
          return defaultNumber(this.step, DEFAULT_STEP);
        },
        computedMin: function computedMin() {
          return defaultNumber(this.min, DEFAULT_MIN);
        },
        computedMax: function computedMax() {
          return defaultNumber(this.max, DEFAULT_MAX);
        },
        computedDelay: function computedDelay() {
          return defaultInteger(this.repeatDelay, DEFAULT_REPEAT_DELAY) || DEFAULT_REPEAT_DELAY;
        },
        computedInterval: function computedInterval() {
          return defaultInteger(this.repeatInterval, DEFAULT_REPEAT_INTERVAL) || DEFAULT_REPEAT_INTERVAL;
        },
        computedThreshold: function computedThreshold() {
          return defaultInteger(this.repeatThreshold, DEFAULT_REPEAT_THRESHOLD) || 1;
        },
        computedStepMultiplier: function computedStepMultiplier() {
          return defaultInteger(this.repeatStepMultiplier, DEFAULT_REPEAT_MULTIPLIER) || 1;
        },
        computedPrecision: function computedPrecision() {
          // Quick and dirty way to get the number of decimals
          var step = this.computedStep;
          return Math.floor(step) === step ? 0 : (step.toString().split('.')[1] || '').length;
        },
        computedMultiplier: function computedMultiplier() {
          return Math.pow(10, this.computedPrecision || 0);
        },
        valueAsFixed: function valueAsFixed() {
          var value = this.localValue;
          return isNull(value) ? '' : value.toFixed(this.computedPrecision);
        },
        computedLocale: function computedLocale() {
          var locales = concat(this.locale).filter(identity);
          var nf = new Intl.NumberFormat(locales);
          return nf.resolvedOptions().locale;
        },
        computedRTL: function computedRTL() {
          return isLocaleRTL(this.computedLocale);
        },
        defaultFormatter: function defaultFormatter() {
          // Returns and `Intl.NumberFormat` formatter method reference
          var precision = this.computedPrecision;
          var nf = new Intl.NumberFormat(this.computedLocale, {
            style: 'decimal',
            useGrouping: false,
            minimumIntegerDigits: 1,
            minimumFractionDigits: precision,
            maximumFractionDigits: precision,
            notation: 'standard'
          }); // Return the format method reference
  
          return nf.format;
        }
      },
      watch: {
        value: function value(_value) {
          _value = toFloat(_value); // Will be `NaN` if `value` is `null`
  
          this.localValue = isNaN(_value) ? null : _value;
        },
        localValue: function localValue(value) {
          this.$emit('input', value);
        },
        disabled: function disabled(_disabled) {
          if (_disabled) {
            this.clearRepeat();
          }
        },
        readonly: function readonly(_readonly) {
          if (_readonly) {
            this.clearRepeat();
          }
        }
      },
      created: function created() {
        // Create non reactive properties
        this.$_autoDelayTimer = null;
        this.$_autoRepeatTimer = null;
        this.$_keyIsDown = false;
      },
      beforeDestroy: function beforeDestroy() {
        this.clearRepeat();
      },
      deactivated: function deactivated()
      /* istanbul ignore next */
      {
        this.clearRepeat();
      },
      methods: {
        // --- Public methods ---
        focus: function focus() {
          if (!this.disabled) {
            try {
              this.$refs.spinner.focus();
            } catch (_unused) {}
          }
        },
        blur: function blur() {
          if (!this.disabled) {
            try {
              this.$refs.spinner.blur();
            } catch (_unused2) {}
          }
        },
        // --- Private methods ---
        emitChange: function emitChange() {
          this.$emit('change', this.localValue);
        },
        stepValue: function stepValue(direction) {
          // Sets a new incremented or decremented value, supporting optional wrapping
          // Direction is either +1 or -1 (or a multiple thereof)
          var value = this.localValue;
  
          if (!this.disabled && !isNull(value)) {
            var step = this.computedStep * direction;
            var min = this.computedMin;
            var max = this.computedMax;
            var multiplier = this.computedMultiplier;
            var wrap = this.wrap; // We ensure that the value steps like a native input
  
            value = Math.round((value - min) / step) * step + min + step; // We ensure that precision is maintained (decimals)
  
            value = Math.round(value * multiplier) / multiplier; // Handle if wrapping is enabled
  
            this.localValue = value > max ? wrap ? min : max : value < min ? wrap ? max : min : value;
          }
        },
        onFocusBlur: function onFocusBlur(evt) {
          if (!this.disabled) {
            this.hasFocus = evt.type === 'focus';
          } else {
            this.hasFocus = false;
          }
        },
        stepUp: function stepUp() {
          var multiplier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
          var value = this.localValue;
  
          if (isNull(value)) {
            this.localValue = this.computedMin;
          } else {
            this.stepValue(+1 * multiplier);
          }
        },
        stepDown: function stepDown() {
          var multiplier = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
          var value = this.localValue;
  
          if (isNull(value)) {
            this.localValue = this.wrap ? this.computedMax : this.computedMin;
          } else {
            this.stepValue(-1 * multiplier);
          }
        },
        onKeydown: function onKeydown(evt) {
          var keyCode = evt.keyCode,
              altKey = evt.altKey,
              ctrlKey = evt.ctrlKey,
              metaKey = evt.metaKey;
          /* istanbul ignore if */
  
          if (this.disabled || this.readonly || altKey || ctrlKey || metaKey) {
            return;
          }
  
          if (arrayIncludes([UP$1, DOWN$1, HOME$1, END$1, PAGEUP$1, PAGEDOWN$1], keyCode)) {
            // https://w3c.github.io/aria-practices/#spinbutton
            evt.preventDefault();
            /* istanbul ignore if */
  
            if (this.$_keyIsDown) {
              // Keypress is already in progress
              return;
            }
  
            this.resetTimers();
  
            if (arrayIncludes([UP$1, DOWN$1], keyCode)) {
              // The following use the custom auto-repeat handling
              this.$_keyIsDown = true;
  
              if (keyCode === UP$1) {
                this.handleStepRepeat(evt, this.stepUp);
              } else if (keyCode === DOWN$1) {
                this.handleStepRepeat(evt, this.stepDown);
              }
            } else {
              // These use native OS key repeating
              if (keyCode === PAGEUP$1) {
                this.stepUp(this.computedStepMultiplier);
              } else if (keyCode === PAGEDOWN$1) {
                this.stepDown(this.computedStepMultiplier);
              } else if (keyCode === HOME$1) {
                this.localValue = this.computedMin;
              } else if (keyCode === END$1) {
                this.localValue = this.computedMax;
              }
            }
          }
        },
        onKeyup: function onKeyup(evt) {
          // Emit a change event when the keyup happens
          var keyCode = evt.keyCode,
              altKey = evt.altKey,
              ctrlKey = evt.ctrlKey,
              metaKey = evt.metaKey;
          /* istanbul ignore if */
  
          if (this.disabled || this.readonly || altKey || ctrlKey || metaKey) {
            return;
          }
  
          if (arrayIncludes([UP$1, DOWN$1, HOME$1, END$1, PAGEUP$1, PAGEDOWN$1], keyCode)) {
            this.resetTimers();
            this.$_keyIsDown = false;
            evt.preventDefault();
            this.emitChange();
          }
        },
        handleStepRepeat: function handleStepRepeat(evt, stepper) {
          var _this = this;
  
          var _ref = evt || {},
              type = _ref.type,
              button = _ref.button;
  
          if (!this.disabled && !this.readonly) {
            /* istanbul ignore if */
            if (type === 'mousedown' && button) {
              // We only respond to left (main === 0) button clicks
              return;
            }
  
            this.resetTimers(); // Step the counter initially
  
            stepper(1);
            var threshold = this.computedThreshold;
            var multiplier = this.computedStepMultiplier;
            var delay = this.computedDelay;
            var interval = this.computedInterval; // Initiate the delay/repeat interval
  
            this.$_autoDelayTimer = setTimeout(function () {
              var count = 0;
              _this.$_autoRepeatTimer = setInterval(function () {
                // After N initial repeats, we increase the incrementing step amount
                // We do this to minimize screen reader announcements of the value
                // (values are announced every change, which can be chatty for SR users)
                // And to make it easer to select a value when the range is large
                stepper(count < threshold ? 1 : multiplier);
                count++;
              }, interval);
            }, delay);
          }
        },
        onMouseup: function onMouseup(evt) {
          // `<body>` listener, only enabled when mousedown starts
          var _ref2 = evt || {},
              type = _ref2.type,
              button = _ref2.button;
          /* istanbul ignore if */
  
  
          if (type === 'mouseup' && button) {
            // Ignore non left button (main === 0) mouse button click
            return;
          }
  
          evt.preventDefault();
          this.resetTimers();
          this.setMouseup(false); // Trigger the change event
  
          this.emitChange();
        },
        setMouseup: function setMouseup(on) {
          // Enable or disabled the body mouseup/touchend handlers
          // Use try/catch to handle case when called server side
          try {
            eventOnOff(on, document.body, 'mouseup', this.onMouseup, false);
            eventOnOff(on, document.body, 'touchend', this.onMouseup, false);
          } catch (_unused3) {}
        },
        resetTimers: function resetTimers() {
          clearTimeout(this.$_autoDelayTimer);
          clearInterval(this.$_autoRepeatTimer);
        },
        clearRepeat: function clearRepeat() {
          this.resetTimers();
          this.setMouseup(false);
          this.$_keyIsDown = false;
        }
      },
      render: function render(h) {
        var _this2 = this,
            _class;
  
        var spinId = this.safeId();
        var value = this.localValue;
        var isVertical = this.vertical;
        var isInline = this.inline && !isVertical;
        var isDisabled = this.disabled;
        var isReadonly = this.readonly && !isDisabled;
        var isRequired = this.required && !isReadonly && !isDisabled;
        var state = this.state;
        var size = this.size;
        var hasValue = !isNull(value);
        var formatter = isFunction(this.formatterFn) ? this.formatterFn : this.defaultFormatter;
  
        var makeButton = function makeButton(stepper, label, IconCmp, keyRef, shortcut, btnDisabled) {
          var $icon = h(IconCmp, {
            props: {
              scale: _this2.hasFocus ? 1.5 : 1.25
            },
            attrs: {
              'aria-hidden': 'true'
            }
          });
  
          var handler = function handler(evt) {
            if (!isDisabled && !isReadonly) {
              evt.preventDefault();
  
              _this2.setMouseup(true);
  
              try {
                // Since we `preventDefault()`, we must manually focus the button
                evt.currentTarget.focus();
              } catch (_unused4) {}
  
              _this2.handleStepRepeat(evt, stepper);
            }
          };
  
          return h('button', {
            key: keyRef || null,
            ref: keyRef,
            staticClass: 'btn btn-sm border-0 rounded-0',
            class: {
              'py-0': !isVertical
            },
            attrs: {
              tabindex: '-1',
              type: 'button',
              disabled: isDisabled || isReadonly || btnDisabled,
              'aria-disabled': isDisabled || isReadonly || btnDisabled ? 'true' : null,
              'aria-controls': spinId,
              'aria-label': label || null,
              'aria-keyshortcuts': shortcut || null
            },
            on: {
              mousedown: handler,
              touchstart: handler
            }
          }, [h('div', {}, [$icon])]);
        }; // TODO: Add button disabled state when `wrap` is `false` and at value max/min
  
  
        var $increment = makeButton(this.stepUp, this.labelIncrement, BIconPlus, 'inc', 'ArrowUp');
        var $decrement = makeButton(this.stepDown, this.labelDecrement, BIconDash, 'dec', 'ArrowDown');
        var $hidden = h();
  
        if (this.name && !isDisabled) {
          $hidden = h('input', {
            key: 'hidden',
            attrs: {
              type: 'hidden',
              name: this.name,
              form: this.form || null,
              // TODO: Should this be set to '' if value is out of range?
              value: this.valueAsFixed
            }
          });
        }
  
        var $spin = h( // We use 'output' element to make this accept a `<label for="id">` (Except IE)
        'output', {
          ref: 'spinner',
          key: 'output',
          staticClass: 'flex-grow-1',
          class: {
            'w-100': !isVertical && !isInline,
            'd-flex': isVertical,
            'align-self-center': !isVertical,
            'align-items-center': isVertical,
            'py-1': isVertical,
            'px-1': !isVertical,
            'mx-1': isVertical,
            'border-top': isVertical,
            'border-bottom': isVertical,
            'border-left': !isVertical,
            'border-right': !isVertical
          },
          attrs: _objectSpread2({
            dir: this.computedRTL ? 'rtl' : 'ltr'
          }, this.$attrs, {
            id: spinId,
            role: 'spinbutton',
            tabindex: isDisabled ? null : '0',
            'aria-live': 'off',
            'aria-label': this.ariaLabel || null,
            'aria-controls': this.ariaControls || null,
            // TODO: May want to check if the value is in range
            'aria-invalid': state === false || !hasValue && isRequired ? 'true' : null,
            'aria-required': isRequired ? 'true' : null,
            // These attrs are required for role spinbutton
            'aria-valuemin': toString$1(this.computedMin),
            'aria-valuemax': toString$1(this.computedMax),
            // These should be `null` if the value is out of range
            // They must also be non-existent attrs if the value is out of range or `null`
            'aria-valuenow': hasValue ? value : null,
            'aria-valuetext': hasValue ? formatter(value) : null
          })
        }, [h('bdi', {
          staticClass: 'w-100'
        }, hasValue ? formatter(value) : this.placeholder || '')]);
        return h('div', {
          staticClass: 'b-form-spinbutton form-control p-0',
          class: (_class = {
            disabled: isDisabled,
            readonly: isReadonly,
            focus: this.hasFocus
          }, _defineProperty(_class, "form-control-".concat(size), !!size), _defineProperty(_class, 'd-inline-flex', isInline || isVertical), _defineProperty(_class, 'd-flex', !isInline && !isVertical), _defineProperty(_class, 'align-items-stretch', !isVertical), _defineProperty(_class, 'flex-column', isVertical), _defineProperty(_class, 'is-valid', state === true), _defineProperty(_class, 'is-invalid', state === false), _class),
          attrs: {
            role: 'group',
            lang: this.computedLocale,
            tabindex: isDisabled ? null : '-1',
            title: this.ariaLabel
          },
          on: {
            keydown: this.onKeydown,
            keyup: this.onKeyup,
            // We use capture phase (`!` prefix) since focus and blur do not bubble
            '!focus': this.onFocusBlur,
            '!blur': this.onFocusBlur
          }
        }, isVertical ? [$increment, $hidden, $spin, $decrement] : [$decrement, $hidden, $spin, $increment]);
      }
    });
  
    var FormSpinbuttonPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormSpinbutton: BFormSpinbutton,
        BSpinbutton: BFormSpinbutton
      }
    });
  
    var NAME$i = 'BFormTag';
    var BFormTag = /*#__PURE__*/Vue.extend({
      name: NAME$i,
      mixins: [idMixin, normalizeSlotMixin],
      props: {
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$i, 'variant');
          }
        },
        disabled: {
          type: Boolean,
          default: false
        },
        title: {
          type: String,
          default: null
        },
        pill: {
          type: Boolean,
          default: false
        },
        removeLabel: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$i, 'removeLabel');
          }
        },
        tag: {
          type: String,
          default: 'span'
        }
      },
      methods: {
        onDelete: function onDelete(evt) {
          var type = evt.type,
              keyCode = evt.keyCode;
  
          if (!this.disabled && (type === 'click' || type === 'keydown' && keyCode === KEY_CODES.DELETE)) {
            this.$emit('remove');
          }
        }
      },
      render: function render(h) {
        var tagId = this.safeId();
        var tagLabelId = this.safeId('_taglabel_');
        var $remove = h();
  
        if (!this.disabled) {
          $remove = h(BButtonClose, {
            staticClass: 'b-form-tag-remove ml-1',
            props: {
              ariaLabel: this.removeLabel
            },
            attrs: {
              'aria-controls': tagId,
              'aria-describedby': tagLabelId,
              'aria-keyshortcuts': 'Delete'
            },
            on: {
              click: this.onDelete,
              keydown: this.onDelete
            }
          });
        }
  
        var $tag = h('span', {
          staticClass: 'b-form-tag-content flex-grow-1 text-truncate',
          attrs: {
            id: tagLabelId
          }
        }, this.normalizeSlot('default') || this.title || [h()]);
        return h(BBadge, {
          staticClass: 'b-form-tag d-inline-flex align-items-baseline mw-100',
          class: {
            disabled: this.disabled
          },
          attrs: {
            id: tagId,
            title: this.title || null,
            'aria-labelledby': tagLabelId
          },
          props: {
            tag: this.tag,
            variant: this.variant,
            pill: this.pill
          }
        }, [$tag, $remove]);
      }
    });
  
    var NAME$j = 'BFormTags'; // Supported input types (for built in input)
  
    var TYPES$1 = ['text', 'email', 'tel', 'url', 'number']; // Pre-compiled regular expressions for performance reasons
  
    var RX_SPACES = /[\s\uFEFF\xA0]+/g; // KeyCode constants
  
    var ENTER$1 = KEY_CODES.ENTER,
        BACKSPACE = KEY_CODES.BACKSPACE,
        DELETE = KEY_CODES.DELETE; // --- Utility methods ---
    // Escape special chars in string and replace
    // contiguous spaces with a whitespace match
  
    var escapeRegExpChars = function escapeRegExpChars(str) {
      return escapeRegExp(str).replace(RX_SPACES, '\\s');
    }; // Remove leading/trailing spaces from array of tags and remove duplicates
  
  
    var cleanTags = function cleanTags(tags) {
      return concat(tags).map(function (tag) {
        return trim(toString$1(tag));
      }).filter(function (tag, index, arr) {
        return tag.length > 0 && arr.indexOf(tag) === index;
      });
    }; // Processes an input/change event, normalizing string or event argument
  
  
    var processEventValue = function processEventValue(evt) {
      return isString(evt) ? evt : isEvent(evt) ? evt.target.value || '' : '';
    }; // Returns a fresh empty `tagsState` object
  
  
    var cleanTagsState = function cleanTagsState() {
      return {
        all: [],
        valid: [],
        invalid: [],
        duplicate: []
      };
    }; // @vue/component
  
  
    var BFormTags = /*#__PURE__*/Vue.extend({
      name: NAME$j,
      mixins: [idMixin, normalizeSlotMixin],
      model: {
        // Even though this is the default that Vue assumes, we need
        // to add it for the docs to reflect that this is the model
        prop: 'value',
        event: 'input'
      },
      props: {
        inputId: {
          type: String,
          default: null
        },
        placeholder: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'placeholder');
          }
        },
        disabled: {
          type: Boolean,
          default: false
        },
        name: {
          type: String,
          default: null
        },
        form: {
          type: String,
          default: null
        },
        autofocus: {
          type: Boolean,
          default: false
        },
        state: {
          // Tri-state: `true`, `false`, `null`
          type: Boolean,
          default: null
        },
        size: {
          type: String,
          default: null
        },
        inputType: {
          type: String,
          default: 'text',
          validator: function validator(type) {
            return arrayIncludes(TYPES$1, type);
          }
        },
        inputClass: {
          type: [String, Array, Object],
          default: null
        },
        inputAttrs: {
          // Additional attributes to add to the input element
          type: Object,
          default: function _default() {
            return {};
          }
        },
        addButtonText: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'addButtonText');
          }
        },
        addButtonVariant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'addButtonVariant');
          }
        },
        tagVariant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'tagVariant');
          }
        },
        tagClass: {
          type: [String, Array, Object],
          default: null
        },
        tagPills: {
          type: Boolean,
          default: false
        },
        tagRemoveLabel: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'tagRemoveLabel');
          }
        },
        tagRemovedLabel: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'tagRemovedLabel');
          }
        },
        tagValidator: {
          type: Function,
          default: null
        },
        duplicateTagText: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'duplicateTagText');
          }
        },
        invalidTagText: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$j, 'invalidTagText');
          }
        },
        separator: {
          // Character (or characters) that trigger adding tags
          type: [String, Array],
          default: null
        },
        removeOnDelete: {
          // Enable deleting last tag in list when BACKSPACE is
          // pressed and input is empty
          type: Boolean,
          default: false
        },
        addOnChange: {
          // Enable change event triggering tag addition
          // Handy if using <select> as the input
          type: Boolean,
          default: false
        },
        noAddOnEnter: {
          // Disable ENTER key from triggering tag addition
          type: Boolean,
          default: false
        },
        noOuterFocus: {
          // Disable the focus ring on the root element
          type: Boolean,
          default: false
        },
        value: {
          // The v-model prop
          type: Array,
          default: function _default() {
            return [];
          }
        }
      },
      data: function data() {
        return {
          hasFocus: false,
          newTag: '',
          tags: [],
          // Tags that were removed
          removedTags: [],
          // Populated when tags are parsed
          tagsState: cleanTagsState()
        };
      },
      computed: {
        computedInputId: function computedInputId() {
          return this.inputId || this.safeId('__input__');
        },
        computedInputType: function computedInputType() {
          // We only allow certain types
          return arrayIncludes(TYPES$1, this.inputType) ? this.inputType : 'text';
        },
        computedInputAttrs: function computedInputAttrs() {
          return _objectSpread2({}, this.inputAttrs, {
            // Must have attributes
            id: this.computedInputId,
            value: this.newTag,
            disabled: this.disabled || null,
            form: this.form || null
          });
        },
        computedInputHandlers: function computedInputHandlers() {
          return {
            input: this.onInputInput,
            change: this.onInputChange,
            keydown: this.onInputKeydown
          };
        },
        computedSeparator: function computedSeparator() {
          // Merge the array into a string
          return concat(this.separator).filter(isString).filter(identity).join('');
        },
        computedSeparatorRegExp: function computedSeparatorRegExp() {
          // We use a computed prop here to precompile the RegExp
          // The RegExp is a character class RE in the form of `/[abc]+/`
          // where a, b, and c are the valid separator characters
          // -> `tags = str.split(/[abc]+/).filter(t => t)`
          var separator = this.computedSeparator;
          return separator ? new RegExp("[".concat(escapeRegExpChars(separator), "]+")) : null;
        },
        computedJoiner: function computedJoiner() {
          // When tag(s) are invalid or duplicate, we leave them
          // in the input so that the user can see them
          // If there are more than one tag in the input, we use the
          // first separator character as the separator in the input
          // We append a space if the first separator is not a space
          var joiner = this.computedSeparator.charAt(0);
          return joiner !== ' ' ? "".concat(joiner, " ") : joiner;
        },
        disableAddButton: function disableAddButton() {
          var _this = this;
  
          // If 'Add' button should be disabled
          // If the input contains at least one tag that can
          // be added, then the 'Add' button should be enabled
          var newTag = trim(this.newTag);
          return newTag === '' || !this.splitTags(newTag).some(function (t) {
            return !arrayIncludes(_this.tags, t) && _this.validateTag(t);
          });
        },
        duplicateTags: function duplicateTags() {
          return this.tagsState.duplicate;
        },
        hasDuplicateTags: function hasDuplicateTags() {
          return this.duplicateTags.length > 0;
        },
        invalidTags: function invalidTags() {
          return this.tagsState.invalid;
        },
        hasInvalidTags: function hasInvalidTags() {
          return this.invalidTags.length > 0;
        }
      },
      watch: {
        value: function value(newVal) {
          this.tags = cleanTags(newVal);
        },
        tags: function tags(newVal, oldVal) {
          // Update the `v-model` (if it differs from the value prop)
          if (!looseEqual(newVal, this.value)) {
            this.$emit('input', newVal);
          }
  
          if (!looseEqual(newVal, oldVal)) {
            newVal = concat(newVal).filter(identity);
            oldVal = concat(oldVal).filter(identity);
            this.removedTags = oldVal.filter(function (old) {
              return !arrayIncludes(newVal, old);
            });
          }
        },
        tagsState: function tagsState(newVal, oldVal) {
          // Emit a tag-state event when the `tagsState` object changes
          if (!looseEqual(newVal, oldVal)) {
            this.$emit('tag-state', newVal.valid, newVal.invalid, newVal.duplicate);
          }
        }
      },
      created: function created() {
        // We do this in created to make sure an input event emits
        // if the cleaned tags are not equal to the value prop
        this.tags = cleanTags(this.value);
      },
      mounted: function mounted() {
        this.handleAutofocus();
      },
      activated: function activated()
      /* istanbul ignore next */
      {
        this.handleAutofocus();
      },
      methods: {
        addTag: function addTag(newTag) {
          newTag = isString(newTag) ? newTag : this.newTag;
          /* istanbul ignore next */
  
          if (this.disabled || trim(newTag) === '') {
            // Early exit
            return;
          }
  
          var parsed = this.parseTags(newTag); // Add any new tags to the `tags` array, or if the
          // array of `allTags` is empty, we clear the input
  
          if (parsed.valid.length > 0 || parsed.all.length === 0) {
            // Clear the user input element (and leave in any invalid/duplicate tag(s)
  
            /* istanbul ignore if: full testing to be added later */
            if (matches(this.getInput(), 'select')) {
              // The following is needed to properly
              // work with `<select>` elements
              this.newTag = '';
            } else {
              var invalidAndDuplicates = [].concat(_toConsumableArray(parsed.invalid), _toConsumableArray(parsed.duplicate));
              this.newTag = parsed.all.filter(function (tag) {
                return arrayIncludes(invalidAndDuplicates, tag);
              }).join(this.computedJoiner).concat(invalidAndDuplicates.length > 0 ? this.computedJoiner.charAt(0) : '');
            }
          }
  
          if (parsed.valid.length > 0) {
            // We add the new tags in one atomic operation
            // to trigger reactivity once (instead of once per tag)
            // We do this after we update the new tag input value
            // `concat()` can be faster than array spread, when both args are arrays
            this.tags = concat(this.tags, parsed.valid);
          }
  
          this.tagsState = parsed; // Attempt to re-focus the input (specifically for when using the Add
          // button, as the button disappears after successfully adding a tag
  
          this.focus();
        },
        removeTag: function removeTag(tag) {
          var _this2 = this;
  
          /* istanbul ignore next */
          if (this.disabled) {
            return;
          } // TODO:
          //   Add `onRemoveTag(tag)` user method, which if returns `false`
          //   will prevent the tag from being removed (i.e. confirmation)
          //   Or emit cancelable `BvEvent`
  
  
          this.tags = this.tags.filter(function (t) {
            return t !== tag;
          }); // Return focus to the input (if possible)
  
          this.$nextTick(function () {
            _this2.focus();
          });
        },
        // --- Input element event handlers ---
        onInputInput: function onInputInput(evt) {
          /* istanbul ignore next: hard to test composition events */
          if (this.disabled || isEvent(evt) && evt.target.composing) {
            // `evt.target.composing` is set by Vue (`v-model` directive)
            // https://github.com/vuejs/vue/blob/dev/src/platforms/web/runtime/directives/model.js
            return;
          }
  
          var newTag = processEventValue(evt);
          var separatorRe = this.computedSeparatorRegExp;
  
          if (this.newTag !== newTag) {
            this.newTag = newTag;
          } // We ignore leading whitespace for the following
  
  
          newTag = trimLeft(newTag);
  
          if (separatorRe && separatorRe.test(newTag.slice(-1))) {
            // A trailing separator character was entered, so add the tag(s)
            // Note: More than one tag on input event is possible via copy/paste
            this.addTag();
          } else {
            // Validate (parse tags) on input event
            this.tagsState = newTag === '' ? cleanTagsState() : this.parseTags(newTag);
          }
        },
        onInputChange: function onInputChange(evt) {
          // Change is triggered on `<input>` blur, or `<select>` selected
          // This event is opt-in
          if (!this.disabled && this.addOnChange) {
            var newTag = processEventValue(evt);
            /* istanbul ignore next */
  
            if (this.newTag !== newTag) {
              this.newTag = newTag;
            }
  
            this.addTag();
          }
        },
        onInputKeydown: function onInputKeydown(evt) {
          // Early exit
  
          /* istanbul ignore next */
          if (this.disabled || !isEvent(evt)) {
            return;
          }
  
          var keyCode = evt.keyCode;
          var value = evt.target.value || '';
          /* istanbul ignore else: testing to be added later */
  
          if (!this.noAddOnEnter && keyCode === ENTER$1) {
            // Attempt to add the tag when user presses enter
            evt.preventDefault();
            this.addTag();
          } else if (this.removeOnDelete && (keyCode === BACKSPACE || keyCode === DELETE) && value === '') {
            // Remove the last tag if the user pressed backspace/delete and the input is empty
            evt.preventDefault();
            this.tags = this.tags.slice(0, -1);
          }
        },
        // --- Wrapper event handlers ---
        onClick: function onClick(evt) {
          var _this3 = this;
  
          if (!this.disabled && isEvent(evt) && evt.target === evt.currentTarget) {
            this.$nextTick(function () {
              _this3.focus();
            });
          }
        },
        onFocusin: function onFocusin() {
          this.hasFocus = true;
        },
        onFocusout: function onFocusout() {
          this.hasFocus = false;
        },
        handleAutofocus: function handleAutofocus() {
          var _this4 = this;
  
          this.$nextTick(function () {
            requestAF(function () {
              if (_this4.autofocus && !_this4.disabled) {
                _this4.focus();
              }
            });
          });
        },
        // --- Public methods ---
        focus: function focus() {
          if (!this.disabled) {
            try {
              this.getInput().focus();
            } catch (_unused) {}
          }
        },
        blur: function blur() {
          try {
            this.getInput().blur();
          } catch (_unused2) {}
        },
        // --- Private methods ---
        splitTags: function splitTags(newTag) {
          // Split the input into an array of raw tags
          newTag = toString$1(newTag);
          var separatorRe = this.computedSeparatorRegExp; // Split the tag(s) via the optional separator
          // Normally only a single tag is provided, but copy/paste
          // can enter multiple tags in a single operation
  
          return (separatorRe ? newTag.split(separatorRe) : [newTag]).map(trim).filter(identity);
        },
        parseTags: function parseTags(newTag) {
          var _this5 = this;
  
          // Takes `newTag` value and parses it into `validTags`,
          // `invalidTags`, and duplicate tags as an object
          // Split the input into raw tags
          var tags = this.splitTags(newTag); // Base results
  
          var parsed = {
            all: tags,
            valid: [],
            invalid: [],
            duplicate: []
          }; // Parse the unique tags
  
          tags.forEach(function (tag) {
            if (arrayIncludes(_this5.tags, tag) || arrayIncludes(parsed.valid, tag)) {
              // Unique duplicate tags
              if (!arrayIncludes(parsed.duplicate, tag)) {
                parsed.duplicate.push(tag);
              }
            } else if (_this5.validateTag(tag)) {
              // We only add unique/valid tags
              parsed.valid.push(tag);
            } else {
              // Unique invalid tags
              if (!arrayIncludes(parsed.invalid, tag)) {
                parsed.invalid.push(tag);
              }
            }
          });
          return parsed;
        },
        validateTag: function validateTag(tag) {
          // Call the user supplied tag validator
          var validator = this.tagValidator;
          return isFunction(validator) ? validator(tag) : true;
        },
        getInput: function getInput() {
          // Returns the input element reference (or null if not found)
          return select("#".concat(this.computedInputId), this.$el);
        },
        // Default User Interface render
        defaultRender: function defaultRender(_ref) {
          var tags = _ref.tags,
              addTag = _ref.addTag,
              removeTag = _ref.removeTag,
              inputType = _ref.inputType,
              inputAttrs = _ref.inputAttrs,
              inputHandlers = _ref.inputHandlers,
              inputClass = _ref.inputClass,
              tagClass = _ref.tagClass,
              tagVariant = _ref.tagVariant,
              tagPills = _ref.tagPills,
              tagRemoveLabel = _ref.tagRemoveLabel,
              invalidTagText = _ref.invalidTagText,
              duplicateTagText = _ref.duplicateTagText,
              isInvalid = _ref.isInvalid,
              isDuplicate = _ref.isDuplicate,
              disabled = _ref.disabled,
              placeholder = _ref.placeholder,
              addButtonText = _ref.addButtonText,
              addButtonVariant = _ref.addButtonVariant,
              disableAddButton = _ref.disableAddButton;
          var h = this.$createElement; // Make the list of tags
  
          var $tags = tags.map(function (tag) {
            tag = toString$1(tag);
            return h(BFormTag, {
              key: "li-tag__".concat(tag),
              staticClass: 'mt-1 mr-1',
              class: tagClass,
              props: {
                // `BFormTag` will auto generate an ID
                // so we do not need to set the ID prop
                tag: 'li',
                title: tag,
                disabled: disabled,
                variant: tagVariant,
                pill: tagPills,
                removeLabel: tagRemoveLabel
              },
              on: {
                remove: function remove() {
                  return removeTag(tag);
                }
              }
            }, tag);
          }); // Feedback IDs if needed
  
          var invalidFeedbackId = invalidTagText && isInvalid ? this.safeId('__invalid_feedback__') : null;
          var duplicateFeedbackId = duplicateTagText && isDuplicate ? this.safeId('__duplicate_feedback__') : null; // Compute the `aria-describedby` attribute value
  
          var ariaDescribedby = [inputAttrs['aria-describedby'], invalidFeedbackId, duplicateFeedbackId].filter(identity).join(' '); // Input
  
          var $input = h('input', {
            ref: 'input',
            // Directive needed to get `evt.target.composing` set (if needed)
            directives: [{
              name: 'model',
              value: inputAttrs.value
            }],
            staticClass: 'b-form-tags-input w-100 flex-grow-1 p-0 m-0 bg-transparent border-0',
            class: inputClass,
            style: {
              outline: 0,
              minWidth: '5rem'
            },
            attrs: _objectSpread2({}, inputAttrs, {
              'aria-describedby': ariaDescribedby || null,
              type: inputType,
              placeholder: placeholder || null
            }),
            domProps: {
              value: inputAttrs.value
            },
            on: inputHandlers
          }); // Add button
  
          var $button = h(BButton, {
            ref: 'button',
            staticClass: 'b-form-tags-button py-0',
            class: {
              // Only show the button if the tag can be added
              // We use the `invisible` class instead of not rendering
              // the button, so that we maintain layout to prevent
              // the user input from jumping around
              invisible: disableAddButton
            },
            style: {
              fontSize: '90%'
            },
            props: {
              variant: addButtonVariant,
              disabled: disableAddButton
            },
            on: {
              click: function click() {
                return addTag();
              }
            }
          }, [this.normalizeSlot('add-button-text') || addButtonText]); // ID of the tags+input `<ul>` list
          // Note we could concatenate inputAttrs.id with `__TAG__LIST__`
          // But note that the inputID may be null until after mount
          // `safeId` returns `null`, if no user provided ID, until after
          // mount when a unique ID is generated
  
          var tagListId = this.safeId('__TAG__LIST__');
          var $field = h('li', {
            key: '__li-input__',
            staticClass: 'flex-grow-1 mt-1',
            attrs: {
              role: 'none',
              'aria-live': 'off',
              'aria-controls': tagListId
            }
          }, [h('div', {
            staticClass: 'd-flex',
            attrs: {
              role: 'group'
            }
          }, [$input, $button])]); // Wrap in an unordered list element (we use a list for accessibility)
  
          var $ul = h('ul', {
            key: '_tags_list_',
            staticClass: 'list-unstyled mt-n1 mb-0 d-flex flex-wrap align-items-center',
            attrs: {
              id: tagListId
            }
          }, // `concat()` is faster than array spread when args are known to be arrays
          concat($tags, $field)); // Assemble the feedback
  
          var $feedback = h();
  
          if (invalidTagText || duplicateTagText) {
            // Add an aria live region for the invalid/duplicate tag
            // messages if the user has not disabled the messages
            var joiner = this.computedJoiner; // Invalid tag feedback if needed (error)
  
            var $invalid = h();
  
            if (invalidFeedbackId) {
              $invalid = h(BFormInvalidFeedback, {
                key: '_tags_invalid_feedback_',
                props: {
                  id: invalidFeedbackId,
                  forceShow: true
                }
              }, [this.invalidTagText, ': ', this.invalidTags.join(joiner)]);
            } // Duplicate tag feedback if needed (warning, not error)
  
  
            var $duplicate = h();
  
            if (duplicateFeedbackId) {
              $duplicate = h(BFormText, {
                key: '_tags_duplicate_feedback_',
                props: {
                  id: duplicateFeedbackId
                }
              }, [this.duplicateTagText, ': ', this.duplicateTags.join(joiner)]);
            }
  
            $feedback = h('div', {
              key: '_tags_feedback_',
              attrs: {
                'aria-live': 'polite',
                'aria-atomic': 'true'
              }
            }, [$invalid, $duplicate]);
          } // Return the content
  
  
          return [$ul, $feedback];
        }
      },
      render: function render(h) {
        var _this6 = this;
  
        // Scoped slot properties
        var scope = {
          // Array of tags (shallow copy to prevent mutations)
          tags: this.tags.slice(),
          // Methods
          removeTag: this.removeTag,
          addTag: this.addTag,
          // We don't include this in the attrs, as users may want to override this
          inputType: this.computedInputType,
          // <input> v-bind:inputAttrs
          inputAttrs: this.computedInputAttrs,
          // <input> v-on:inputHandlers
          inputHandlers: this.computedInputHandlers,
          // <input> :id="inputId"
          inputId: this.computedInputId,
          // Invalid/Duplicate state information
          invalidTags: this.invalidTags.slice(),
          isInvalid: this.hasInvalidTags,
          duplicateTags: this.duplicateTags.slice(),
          isDuplicate: this.hasDuplicateTags,
          // If the 'Add' button should be disabled
          disableAddButton: this.disableAddButton,
          // Pass-though values
          state: this.state,
          separator: this.separator,
          disabled: this.disabled,
          size: this.size,
          placeholder: this.placeholder,
          inputClass: this.inputClass,
          tagRemoveLabel: this.tagRemoveLabel,
          tagVariant: this.tagVariant,
          tagPills: this.tagPills,
          tagClass: this.tagClass,
          addButtonText: this.addButtonText,
          addButtonVariant: this.addButtonVariant,
          invalidTagText: this.invalidTagText,
          duplicateTagText: this.duplicateTagText
        }; // Generate the user interface
  
        var $content = this.normalizeSlot('default', scope) || this.defaultRender(scope); // Generate the `aria-live` region for the current value(s)
  
        var $output = h('output', {
          staticClass: 'sr-only',
          attrs: {
            id: this.safeId('_selected-tags_'),
            role: 'status',
            for: this.computedInputId,
            'aria-live': this.hasFocus ? 'polite' : 'off',
            'aria-atomic': 'true',
            'aria-relevant': 'additions text'
          }
        }, this.tags.join(', ')); // Removed tag live region
  
        var $removed = h('div', {
          staticClass: 'sr-only',
          attrs: {
            id: this.safeId('_removed-tags_'),
            role: 'status',
            'aria-live': this.hasFocus ? 'assertive' : 'off',
            'aria-atomic': 'true'
          }
        }, this.removedTags.length > 0 ? "(".concat(this.tagRemovedLabel, ") ").concat(this.removedTags.join(', ')) : ''); // Add hidden inputs for form submission
  
        var $hidden = h();
  
        if (this.name && !this.disabled) {
          // We add hidden inputs for each tag if a name is provided
          // for native submission of forms
          $hidden = this.tags.map(function (tag) {
            return h('input', {
              key: tag,
              attrs: {
                type: 'hidden',
                value: tag,
                name: _this6.name,
                form: _this6.form || null
              }
            });
          });
        } // Return the rendered output
  
  
        return h('div', {
          staticClass: 'b-form-tags form-control h-auto',
          class: _defineProperty({
            focus: this.hasFocus && !this.noOuterFocus && !this.disabled,
            disabled: this.disabled,
            'is-valid': this.state === true,
            'is-invalid': this.state === false
          }, "form-control-".concat(this.size), this.size),
          attrs: {
            id: this.safeId(),
            role: 'group',
            tabindex: this.disabled || this.noOuterFocus ? null : '-1',
            'aria-describedby': this.safeId('_selected_')
          },
          on: {
            focusin: this.onFocusin,
            focusout: this.onFocusout,
            click: this.onClick
          }
        }, concat($output, $removed, $content, $hidden));
      }
    });
  
    var FormTagsPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormTags: BFormTags,
        BTags: BFormTags,
        BFormTag: BFormTag,
        BTag: BFormTag
      }
    });
  
    var BFormTextarea = /*#__PURE__*/Vue.extend({
      name: 'BFormTextarea',
      directives: {
        'b-visible': VBVisible
      },
      mixins: [idMixin, listenOnRootMixin, formMixin, formSizeMixin, formStateMixin, formTextMixin, formSelectionMixin, formValidityMixin],
      props: {
        rows: {
          type: [Number, String],
          default: 2
        },
        maxRows: {
          type: [Number, String],
          default: null
        },
        wrap: {
          // 'soft', 'hard' or 'off'. Browser default is 'soft'
          type: String,
          default: 'soft'
        },
        noResize: {
          // Disable the resize handle of textarea
          type: Boolean,
          default: false
        },
        noAutoShrink: {
          // When in auto resize mode, disable shrinking to content height
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          heightInPx: null
        };
      },
      computed: {
        computedStyle: function computedStyle() {
          var styles = {
            // Setting `noResize` to true will disable the ability for the user to
            // manually resize the textarea. We also disable when in auto height mode
            resize: !this.computedRows || this.noResize ? 'none' : null
          };
  
          if (!this.computedRows) {
            // Conditionally set the computed CSS height when auto rows/height is enabled
            // We avoid setting the style to `null`, which can override user manual resize handle
            styles.height = this.heightInPx; // We always add a vertical scrollbar to the textarea when auto-height is
            // enabled so that the computed height calculation returns a stable value
  
            styles.overflowY = 'scroll';
          }
  
          return styles;
        },
        computedMinRows: function computedMinRows() {
          // Ensure rows is at least 2 and positive (2 is the native textarea value)
          // A value of 1 can cause issues in some browsers, and most browsers
          // only support 2 as the smallest value
          return Math.max(parseInt(this.rows, 10) || 2, 2);
        },
        computedMaxRows: function computedMaxRows() {
          return Math.max(this.computedMinRows, parseInt(this.maxRows, 10) || 0);
        },
        computedRows: function computedRows() {
          // This is used to set the attribute 'rows' on the textarea
          // If auto-height is enabled, then we return `null` as we use CSS to control height
          return this.computedMinRows === this.computedMaxRows ? this.computedMinRows : null;
        }
      },
      watch: {
        localValue: function localValue() {
          this.setHeight();
        }
      },
      mounted: function mounted() {
        this.setHeight();
      },
      methods: {
        // Called by intersection observer directive
        visibleCallback: function visibleCallback(visible)
        /* istanbul ignore next */
        {
          if (visible) {
            // We use a `$nextTick()` here just to make sure any
            // transitions or portalling have completed
            this.$nextTick(this.setHeight);
          }
        },
        setHeight: function setHeight() {
          var _this = this;
  
          this.$nextTick(function () {
            requestAF(function () {
              _this.heightInPx = _this.computeHeight();
            });
          });
        },
        computeHeight: function computeHeight()
        /* istanbul ignore next: can't test getComputedStyle in JSDOM */
        {
          if (this.$isServer || !isNull(this.computedRows)) {
            return null;
          }
  
          var el = this.$el; // Element must be visible (not hidden) and in document
          // Must be checked after above checks
  
          if (!isVisible(el)) {
            return null;
          } // Get current computed styles
  
  
          var computedStyle = getCS(el); // Height of one line of text in px
  
          var lineHeight = parseFloat(computedStyle.lineHeight); // Calculate height of border and padding
  
          var border = (parseFloat(computedStyle.borderTopWidth) || 0) + (parseFloat(computedStyle.borderBottomWidth) || 0);
          var padding = (parseFloat(computedStyle.paddingTop) || 0) + (parseFloat(computedStyle.paddingBottom) || 0); // Calculate offset
  
          var offset = border + padding; // Minimum height for min rows (which must be 2 rows or greater for cross-browser support)
  
          var minHeight = lineHeight * this.computedMinRows + offset; // Get the current style height (with `px` units)
  
          var oldHeight = el.style.height || computedStyle.height; // Probe scrollHeight by temporarily changing the height to `auto`
  
          el.style.height = 'auto';
          var scrollHeight = el.scrollHeight; // Place the original old height back on the element, just in case `computedProp`
          // returns the same value as before
  
          el.style.height = oldHeight; // Calculate content height in 'rows' (scrollHeight includes padding but not border)
  
          var contentRows = Math.max((scrollHeight - padding) / lineHeight, 2); // Calculate number of rows to display (limited within min/max rows)
  
          var rows = Math.min(Math.max(contentRows, this.computedMinRows), this.computedMaxRows); // Calculate the required height of the textarea including border and padding (in pixels)
  
          var height = Math.max(Math.ceil(rows * lineHeight + offset), minHeight); // Computed height remains the larger of `oldHeight` and new `height`,
          // when height is in `sticky` mode (prop `no-auto-shrink` is true)
  
          if (this.noAutoShrink && (parseFloat(oldHeight) || 0) > height) {
            return oldHeight;
          } // Return the new computed CSS height in px units
  
  
          return "".concat(height, "px");
        }
      },
      render: function render(h) {
        // Using self instead of this helps reduce code size during minification
        var self = this;
        return h('textarea', {
          ref: 'input',
          class: self.computedClass,
          style: self.computedStyle,
          directives: [{
            name: 'model',
            value: self.localValue
          }, {
            name: 'b-visible',
            value: this.visibleCallback,
            // If textarea is within 640px of viewport, consider it visible
            modifiers: {
              '640': true
            }
          }],
          attrs: {
            id: self.safeId(),
            name: self.name,
            form: self.form || null,
            disabled: self.disabled,
            placeholder: self.placeholder,
            required: self.required,
            autocomplete: self.autocomplete || null,
            readonly: self.readonly || self.plaintext,
            rows: self.computedRows,
            wrap: self.wrap || null,
            'aria-required': self.required ? 'true' : null,
            'aria-invalid': self.computedAriaInvalid
          },
          domProps: {
            value: self.localValue
          },
          on: _objectSpread2({}, self.$listeners, {
            input: self.onInput,
            change: self.onChange,
            blur: self.onBlur
          })
        });
      }
    });
  
    var FormTextareaPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormTextarea: BFormTextarea,
        BTextarea: BFormTextarea
      }
    });
  
    var NAME$k = 'BTime';
    var NUMERIC = 'numeric';
    var LEFT$1 = KEY_CODES.LEFT,
        RIGHT$1 = KEY_CODES.RIGHT; // Time string RegExpr (optional seconds)
  
    var RE_TIME = /^([0-1]?[0-9]|2[0-3]):[0-5]?[0-9](:[0-5]?[0-9])?$/; // --- Helpers ---
    // Fallback to BFormSpinbutton prop if no value found
  
    var getConfigFallback$1 = function getConfigFallback(prop) {
      return getComponentConfig(NAME$k, prop) || getComponentConfig('BFormSpinbutton', prop);
    };
  
    var padLeftZeros = function padLeftZeros(num) {
      return "00".concat(num || '').slice(-2);
    };
  
    var parseHMS = function parseHMS(hms) {
      hms = toString$1(hms);
      var hh = null,
          mm = null,
          ss = null;
  
      if (RE_TIME.test(hms)) {
  
        var _hms$split$map$map = hms.split(':').map(toInteger).map(function (v) {
          return isNaN(v) ? null : v;
        });
  
        var _hms$split$map$map2 = _slicedToArray(_hms$split$map$map, 3);
  
        hh = _hms$split$map$map2[0];
        mm = _hms$split$map$map2[1];
        ss = _hms$split$map$map2[2];
      }
  
      return {
        hours: isUndefinedOrNull(hh) ? null : hh,
        minutes: isUndefinedOrNull(mm) ? null : mm,
        seconds: isUndefinedOrNull(ss) ? null : ss,
        ampm: isUndefinedOrNull(hh) || hh < 12 ? 0 : 1
      };
    };
  
    var formatHMS = function formatHMS(_ref) {
      var hours = _ref.hours,
          minutes = _ref.minutes,
          seconds = _ref.seconds;
      var requireSeconds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  
      if (isNull(hours) || isNull(minutes) || requireSeconds && isNull(seconds)) {
        return '';
      }
  
      var hms = [hours, minutes, requireSeconds ? seconds : 0];
      return hms.map(padLeftZeros).join(':');
    }; // @vue/component
  
  
    var BTime = /*#__PURE__*/Vue.extend({
      name: NAME$k,
      mixins: [idMixin, normalizeSlotMixin],
      model: {
        prop: 'value',
        event: 'input'
      },
      props: {
        value: {
          type: String,
          default: ''
        },
        showSeconds: {
          // If true, show the second spinbutton
          type: Boolean,
          default: false
        },
        hour12: {
          // Explicitly force 12 or 24 hour time
          // Default is to use resolved locale for 12/24 hour display
          // Tri-state: `true` = 12, `false` = 24, `null` = auto
          type: Boolean,
          default: null
        },
        locale: {
          type: [String, Array],
          default: null
        },
        ariaLabelledby: {
          // ID of label element
          type: String,
          default: null
        },
        secondsStep: {
          type: [Number, String],
          default: 1
        },
        minutesStep: {
          type: [Number, String],
          default: 1
        },
        disabled: {
          type: Boolean,
          default: false
        },
        readonly: {
          type: Boolean,
          default: false
        },
        hideHeader: {
          type: Boolean,
          default: false
        },
        labelNoTimeSelected: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelNoTimeSelected');
          }
        },
        labelSelected: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelSelected');
          }
        },
        labelHours: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelHours');
          }
        },
        labelMinutes: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelMinutes');
          }
        },
        labelSeconds: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelSeconds');
          }
        },
        labelAmpm: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelAmpm');
          }
        },
        labelAm: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelAm');
          }
        },
        labelPm: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$k, 'labelPm');
          }
        },
        // Passed to the spin buttons
        labelIncrement: {
          type: String,
          // Falls back to BFormSpinbutton label
          default: function _default() {
            return getConfigFallback$1('labelIncrement');
          }
        },
        labelDecrement: {
          type: String,
          // Falls back to BFormSpinbutton label
          default: function _default() {
            return getConfigFallback$1('labelDecrement');
          }
        },
        hidden: {
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        var parsed = parseHMS(this.value || '');
        return {
          // Spin button models
          modelHours: parsed.hours,
          modelMinutes: parsed.minutes,
          modelSeconds: parsed.seconds,
          modelAmpm: parsed.ampm,
          // Internal flag to enable aria-live regions
          isLive: false
        };
      },
      computed: {
        computedHMS: function computedHMS() {
          var hours = this.modelHours;
          var minutes = this.modelMinutes;
          var seconds = this.modelSeconds;
          return formatHMS({
            hours: hours,
            minutes: minutes,
            seconds: seconds
          }, this.showSeconds);
        },
        resolvedOptions: function resolvedOptions() {
          // Resolved locale options
          var locale = concat(this.locale).filter(identity);
          var options = {
            hour: NUMERIC,
            minute: NUMERIC,
            second: NUMERIC
          };
  
          if (!isUndefinedOrNull(this.hour12)) {
            // Force 12 or 24 hour clock
            options.hour12 = !!this.hour12;
          }
  
          var dtf = new Intl.DateTimeFormat(locale, options);
          var resolved = dtf.resolvedOptions();
          var hour12 = resolved.hour12 || false; // IE 11 doesn't resolve the hourCycle, so we make
          // an assumption and fall back to common values
  
          var hourCycle = resolved.hourCycle || (hour12 ? 'h12' : 'h23');
          return {
            locale: resolved.locale,
            hour12: hour12,
            hourCycle: hourCycle
          };
        },
        computedLocale: function computedLocale() {
          return this.resolvedOptions.locale;
        },
        computedLang: function computedLang() {
          return (this.computedLocale || '').replace(/-u-.*$/, '');
        },
        computedRTL: function computedRTL() {
          return isLocaleRTL(this.computedLang);
        },
        computedHourCycle: function computedHourCycle() {
          // h11, h12, h23, or h24
          // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Locale/hourCycle
          // h12 - Hour system using 1–12. Corresponds to 'h' in patterns. The 12 hour clock, with midnight starting at 12:00 am
          // h23 - Hour system using 0–23. Corresponds to 'H' in patterns. The 24 hour clock, with midnight starting at 0:00
          // h11 - Hour system using 0–11. Corresponds to 'K' in patterns. The 12 hour clock, with midnight starting at 0:00 am
          // h24 - Hour system using 1–24. Corresponds to 'k' in pattern. The 24 hour clock, with midnight starting at 24:00
          // For h12 or h24, we visually format 00 hours as 12
          return this.resolvedOptions.hourCycle;
        },
        is12Hour: function is12Hour() {
          return !!this.resolvedOptions.hour12;
        },
        context: function context() {
          return {
            locale: this.computedLocale,
            isRTL: this.computedRTL,
            hourCycle: this.computedHourCycle,
            hour12: this.is12Hour,
            hours: this.modelHours,
            minutes: this.modelMinutes,
            seconds: this.showSeconds ? this.modelSeconds : 0,
            value: this.computedHMS,
            formatted: this.formattedTimeString
          };
        },
        valueId: function valueId() {
          return this.safeId() || null;
        },
        computedAriaLabelledby: function computedAriaLabelledby() {
          return [this.ariaLabelledby, this.valueId].filter(identity).join(' ') || null;
        },
        timeFormatter: function timeFormatter() {
          // Returns a formatter function reference
          // The formatter converts the time to a localized string
          var options = {
            hour12: this.is12Hour,
            hourCycle: this.computedHourCycle,
            hour: NUMERIC,
            minute: NUMERIC,
            timeZone: 'UTC'
          };
  
          if (this.showSeconds) {
            options.second = NUMERIC;
          } // Formats the time as a localized string
  
  
          return createDateFormatter(this.computedLocale, options);
        },
        numberFormatter: function numberFormatter() {
          // Returns a formatter function reference
          // The formatter always formats as 2 digits and is localized
          var nf = new Intl.NumberFormat(this.computedLocale, {
            style: 'decimal',
            minimumIntegerDigits: 2,
            minimumFractionDigits: 0,
            maximumFractionDigits: 0,
            notation: 'standard'
          });
          return nf.format;
        },
        formattedTimeString: function formattedTimeString() {
          var hours = this.modelHours;
          var minutes = this.modelMinutes;
          var seconds = this.showSeconds ? this.modelSeconds || 0 : 0;
  
          if (this.computedHMS) {
            return this.timeFormatter(createDate(Date.UTC(0, 0, 1, hours, minutes, seconds)));
          }
  
          return this.labelNoTimeSelected || ' ';
        }
      },
      watch: {
        value: function value(newVal, oldVal) {
          if (newVal !== oldVal && !looseEqual(parseHMS(newVal), parseHMS(this.computedHMS))) {
            var _parseHMS = parseHMS(newVal),
                hours = _parseHMS.hours,
                minutes = _parseHMS.minutes,
                seconds = _parseHMS.seconds,
                ampm = _parseHMS.ampm;
  
            this.modelHours = hours;
            this.modelMinutes = minutes;
            this.modelSeconds = seconds;
            this.modelAmpm = ampm;
          }
        },
        computedHMS: function computedHMS(newVal, oldVal) {
          if (newVal !== oldVal) {
            this.$emit('input', newVal);
          }
        },
        context: function context(newVal, oldVal) {
          if (!looseEqual(newVal, oldVal)) {
            this.$emit('context', newVal);
          }
        },
        modelAmpm: function modelAmpm(newVal, oldVal) {
          var _this = this;
  
          if (newVal !== oldVal) {
            var hours = isNull(this.modelHours) ? 0 : this.modelHours;
            this.$nextTick(function () {
              if (newVal === 0 && hours > 11) {
                // Switched to AM
                _this.modelHours = hours - 12;
              } else if (newVal === 1 && hours < 12) {
                // Switched to PM
                _this.modelHours = hours + 12;
              }
            });
          }
        },
        modelHours: function modelHours(newHours, oldHours) {
          if (newHours !== oldHours) {
            this.modelAmpm = newHours > 11 ? 1 : 0;
          }
        }
      },
      created: function created() {
        var _this2 = this;
  
        this.$nextTick(function () {
          _this2.$emit('context', _this2.context);
        });
      },
      mounted: function mounted() {
        this.setLive(true);
      },
      activated: function activated()
      /* istanbul ignore next */
      {
        this.setLive(true);
      },
      deactivated: function deactivated()
      /* istanbul ignore next */
      {
        this.setLive(false);
      },
      beforeDestroy: function beforeDestroy() {
        this.setLive(false);
      },
      methods: {
        // Public methods
        focus: function focus() {
          if (!this.disabled) {
            try {
              // We focus the first spin button
              this.$refs.spinners[0].focus();
            } catch (_unused) {}
          }
        },
        blur: function blur() {
          if (!this.disabled) {
            try {
              if (contains(this.$el, document.activeElement)) {
                document.activeElement.blur();
              }
            } catch (_unused2) {}
          }
        },
        // Formatters for the spin buttons
        formatHours: function formatHours(hh) {
          var hourCycle = this.computedHourCycle; // We always store 0-23, but format based on h11/h12/h23/h24 formats
  
          hh = this.is12Hour && hh > 12 ? hh - 12 : hh; // Determine how 00:00 and 12:00 are shown
  
          hh = hh === 0 && hourCycle === 'h12' ? 12 : hh === 0 && hourCycle === 'h24' ? 24 : hh === 12 && hourCycle === 'h11' ? 0 : hh;
          return this.numberFormatter(hh);
        },
        formatMinutes: function formatMinutes(mm) {
          return this.numberFormatter(mm);
        },
        formatSeconds: function formatSeconds(ss) {
          return this.numberFormatter(ss);
        },
        formatAmpm: function formatAmpm(ampm) {
          // These should come from label props???
          // `ampm` should always be a value of `0` or `1`
          return ampm === 0 ? this.labelAm : ampm === 1 ? this.labelPm : '';
        },
        // Spinbutton on change handlers
        setHours: function setHours(value) {
          this.modelHours = value;
        },
        setMinutes: function setMinutes(value) {
          this.modelMinutes = value;
        },
        setSeconds: function setSeconds(value) {
          this.modelSeconds = value;
        },
        setAmpm: function setAmpm(value) {
          this.modelAmpm = value;
        },
        onSpinLeftRight: function onSpinLeftRight() {
          var evt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
          var type = evt.type,
              keyCode = evt.keyCode;
  
          if (!this.disabled && type === 'keydown' && (keyCode === LEFT$1 || keyCode === RIGHT$1)) {
            evt.preventDefault();
            evt.stopPropagation();
            var spinners = this.$refs.spinners || [];
            var index = spinners.map(function (cmp) {
              return !!cmp.hasFocus;
            }).indexOf(true);
            index = index + (keyCode === LEFT$1 ? -1 : 1);
            index = index >= spinners.length ? 0 : index < 0 ? spinners.length - 1 : index;
  
            try {
              spinners[index].focus();
            } catch (_unused3) {}
          }
        },
        setLive: function setLive(on) {
          var _this3 = this;
  
          if (on) {
            this.$nextTick(function () {
              requestAF(function () {
                _this3.isLive = true;
              });
            });
          } else {
            this.isLive = false;
          }
        }
      },
      render: function render(h) {
        var _this4 = this;
  
        /* istanbul ignore if */
        if (this.hidden) {
          // If hidden, we just render a placeholder comment
          return h();
        }
  
        var valueId = this.valueId;
        var computedAriaLabelledby = this.computedAriaLabelledby;
        var spinIds = []; // Helper method to render a spinbutton
  
        var makeSpinbutton = function makeSpinbutton(handler, key, classes) {
          var spinbuttonProps = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
          var id = _this4.safeId("_spinbutton_".concat(key, "_")) || null;
          spinIds.push(id);
          return h(BFormSpinbutton, {
            key: key,
            ref: 'spinners',
            refInFor: true,
            class: classes,
            props: _objectSpread2({
              id: id,
              placeholder: '--',
              vertical: true,
              required: true,
              disabled: _this4.disabled,
              readonly: _this4.readonly,
              locale: _this4.computedLocale,
              labelIncrement: _this4.labelIncrement,
              labelDecrement: _this4.labelDecrement,
              wrap: true,
              ariaControls: valueId,
              min: 0
            }, spinbuttonProps),
            on: {
              // We use `change` event to minimize SR verbosity
              // As the spinbutton will announce each value change
              // and we don't want the formatted time to be announced
              // on each value input if repeat is happening
              change: handler
            }
          });
        }; // Helper method to return a "colon" separator
  
  
        var makeColon = function makeColon() {
          return h('div', {
            staticClass: 'd-flex flex-column',
            class: {
              'text-muted': _this4.disabled || _this4.readonly
            },
            attrs: {
              'aria-hidden': 'true'
            }
          }, [h(BIconCircleFill, {
            props: {
              shiftV: 4,
              scale: 0.5
            }
          }), h(BIconCircleFill, {
            props: {
              shiftV: -4,
              scale: 0.5
            }
          })]);
        };
  
        var $spinners = []; // Hours
  
        $spinners.push(makeSpinbutton(this.setHours, 'hours', '', {
          value: this.modelHours,
          max: 23,
          step: 1,
          formatterFn: this.formatHours,
          ariaLabel: this.labelHours
        })); // Spacer
  
        $spinners.push(makeColon()); // Minutes
  
        $spinners.push(makeSpinbutton(this.setMinutes, 'minutes', '', {
          value: this.modelMinutes,
          max: 59,
          step: this.minutesStep || 1,
          formatterFn: this.formatMinutes,
          ariaLabel: this.labelMinutes
        }));
  
        if (this.showSeconds) {
          // Spacer
          $spinners.push(makeColon()); // Seconds
  
          $spinners.push(makeSpinbutton(this.setSeconds, 'seconds', '', {
            value: this.modelSeconds,
            max: 59,
            step: this.secondsStep || 1,
            formatterFn: this.formatSeconds,
            ariaLabel: this.labelSeconds
          }));
        } // AM/PM ?
  
  
        if (this.is12Hour) {
          // TODO:
          //   If locale is RTL, unshift this instead of push?
          //   And switch class `ml-2` to `mr-2`
          //   Note some LTR locales (i.e. zh) also place AM/PM to the left
          $spinners.push(makeSpinbutton(this.setAmpm, 'ampm', 'ml-2', {
            value: this.modelAmpm,
            max: 1,
            formatterFn: this.formatAmpm,
            ariaLabel: this.labelAmpm,
            // We set `required` as `false`, since this always has a value
            required: false
          }));
        } // Assemble spinners
  
  
        $spinners = h('div', {
          staticClass: 'd-flex align-items-center justify-content-center mx-auto',
          attrs: {
            role: 'group',
            tabindex: this.disabled || this.readonly ? null : '-1',
            'aria-labelledby': computedAriaLabelledby
          },
          on: {
            keydown: this.onSpinLeftRight,
            click: function click(evt)
            /* istanbul ignore next */
            {
              if (evt.target === evt.currentTarget) {
                _this4.focus();
              }
            }
          }
        }, $spinners); // Selected type display
  
        var $value = h('output', {
          staticClass: 'border rounded d-block p-1 small text-center',
          class: {
            disabled: this.disabled || this.readonly
          },
          attrs: {
            id: valueId,
            role: 'status',
            for: spinIds.filter(identity).join(' ') || null,
            tabindex: this.disabled ? null : '-1',
            'aria-live': this.isLive ? 'polite' : 'off',
            'aria-atomic': 'true'
          },
          on: {
            // Transfer focus/click to focus hours spinner
            click: this.focus,
            focus: this.focus
          }
        }, [h('bdi', this.formattedTimeString), this.computedHMS ? h('span', {
          staticClass: 'sr-only'
        }, " (".concat(this.labelSelected, ") ")) : '']);
        var $header = h('header', {
          class: {
            'sr-only': this.hideHeader,
            'mb-2': !this.hideHeader
          }
        }, [$value]); // Optional bottom slot
  
        var $slot = this.normalizeSlot('default');
        $slot = $slot ? h('footer', {
          staticClass: 'mt-2'
        }, $slot) : h();
        return h('div', {
          staticClass: 'b-time d-inline-flex flex-column text-center',
          attrs: {
            role: 'group',
            lang: this.computedLang || null,
            'aria-labelledby': computedAriaLabelledby || null,
            'aria-disabled': this.disabled ? 'true' : null,
            'aria-readonly': this.readonly && !this.disabled ? 'true' : null
          }
        }, [$header, $spinners, $slot]);
      }
    });
  
    var NAME$l = 'BFormTimepicker'; // Fallback to BTime/BFormSpinbutton prop if no value found
  
    var getConfigFallback$2 = function getConfigFallback(prop) {
      return getComponentConfig(NAME$l, prop) || getComponentConfig('BTime', prop) || getComponentConfig('BFormSpinbutton', prop);
    }; // We create our props as a mixin so that we can control
    // where they appear in the props listing reference section
  
  
    var propsMixin$1 = {
      props: _objectSpread2({
        value: {
          type: String,
          default: ''
        },
        resetValue: {
          type: String,
          default: ''
        },
        placeholder: {
          type: String,
          // Defaults to `labelNoTime` from BTime context
          default: null
        },
        size: {
          type: String,
          default: null
        },
        disabled: {
          type: Boolean,
          default: false
        },
        readonly: {
          type: Boolean,
          default: false
        },
        required: {
          // If true adds the `aria-required` attribute
          type: Boolean,
          default: false
        },
        name: {
          type: String,
          default: null
        },
        form: {
          type: String,
          default: null
        },
        state: {
          // Tri-state prop: `true`, `false` or `null`
          type: Boolean,
          default: null
        },
        hour12: {
          // Tri-state prop: `true` => 12 hour, `false` => 24 hour, `null` => auto
          type: Boolean,
          default: null
        },
        locale: {
          type: [String, Array],
          default: null
        },
        showSeconds: {
          type: Boolean,
          default: false
        },
        hideHeader: {
          type: Boolean,
          default: false
        },
        secondsStep: {
          type: [Number, String],
          default: 1
        },
        minutesStep: {
          type: [Number, String],
          default: 1
        },
        nowButton: {
          type: Boolean,
          default: false
        },
        labelNowButton: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$l, 'labelNowButton');
          }
        },
        nowButtonVariant: {
          type: String,
          default: 'outline-primary'
        },
        resetButton: {
          type: Boolean,
          default: false
        },
        labelResetButton: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$l, 'labelResetButton');
          }
        },
        resetButtonVariant: {
          type: String,
          default: 'outline-danger'
        },
        noCloseButton: {
          type: Boolean,
          default: false
        },
        labelCloseButton: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$l, 'labelCloseButton');
          }
        },
        closeButtonVariant: {
          type: String,
          default: 'outline-secondary'
        },
        // Labels
        // These fallback to BTime values
        labelSelected: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelSelected');
          }
        },
        labelNoTimeSelected: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelNoTimeSelected');
          }
        },
        labelHours: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelHours');
          }
        },
        labelMinutes: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelMinutes');
          }
        },
        labelSeconds: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelSeconds');
          }
        },
        labelAmpm: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelAmpm');
          }
        },
        labelAm: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelAm');
          }
        },
        labelPm: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelPm');
          }
        },
        // These pick BTime or BFormSpinbutton global config if no BFormTimepicker global config
        labelIncrement: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelIncrement');
          }
        },
        labelDecrement: {
          type: String,
          default: function _default() {
            return getConfigFallback$2('labelDecrement');
          }
        },
        // extra dropdown stuff
        menuClass: {
          type: [String, Array, Object],
          default: null
        }
      }, dropdownProps)
    }; // --- BFormDate component ---
    // @vue/component
  
    var BFormTimepicker = /*#__PURE__*/Vue.extend({
      name: NAME$l,
      // The mixins order determines the order of appearance in the props reference section
      mixins: [idMixin, propsMixin$1],
      model: {
        prop: 'value',
        event: 'input'
      },
      data: function data() {
        return {
          // We always use `HH:mm:ss` value internally
          localHMS: this.value || '',
          // Context data from BTime
          localLocale: null,
          isRTL: false,
          formattedValue: '',
          // If the menu is opened
          isVisible: false
        };
      },
      computed: {
        computedLang: function computedLang() {
          return (this.localLocale || '').replace(/-u-.*$/i, '') || null;
        },
        timeProps: function timeProps() {
          // Props we pass to BTime
          // Use self for better minification, as `this` won't
          // minimize and we reference it many times below
          var self = this;
          return {
            hidden: !self.isVisible,
            value: self.localHMS,
            // Passthrough props
            readonly: self.readonly,
            disabled: self.disabled,
            locale: self.locale,
            hour12: self.hour12,
            hideHeader: self.hideHeader,
            showSeconds: self.showSeconds,
            secondsStep: self.secondsStep,
            minutesStep: self.minutesStep,
            labelNoTimeSelected: self.labelNoTimeSelected,
            labelSelected: self.labelSelected,
            labelHours: self.labelHours,
            labelMinutes: self.labelMinutes,
            labelSeconds: self.labelSeconds,
            labelAmpm: self.labelAmpm,
            labelAm: self.labelAm,
            labelPm: self.labelPm,
            labelIncrement: self.labelIncrement,
            labelDecrement: self.labelDecrement
          };
        }
      },
      watch: {
        value: function value(newVal) {
          this.localHMS = newVal || '';
        },
        localHMS: function localHMS(newVal) {
          this.$emit('input', newVal || '');
        }
      },
      methods: {
        // Public methods
        focus: function focus() {
          if (!this.disabled) {
            try {
              this.$refs.control.focus();
            } catch (_unused) {}
          }
        },
        blur: function blur() {
          if (!this.disabled) {
            try {
              this.$refs.control.blur();
            } catch (_unused2) {}
          }
        },
        // Private methods
        setAndClose: function setAndClose(value) {
          var _this = this;
  
          this.localHMS = value;
          this.$nextTick(function () {
            _this.$refs.control.hide(true);
          });
        },
        onInput: function onInput(hms) {
          if (this.localHMS !== hms) {
            this.localHMS = hms;
          }
        },
        onContext: function onContext(ctx) {
          var isRTL = ctx.isRTL,
              locale = ctx.locale,
              value = ctx.value,
              formatted = ctx.formatted;
          this.isRTL = isRTL;
          this.localLocale = locale;
          this.formattedValue = formatted;
          this.localHMS = value || ''; // Re-emit the context event
  
          this.$emit('context', ctx);
        },
        onNowButton: function onNowButton() {
          var now = new Date();
          var hours = now.getHours();
          var minutes = now.getMinutes();
          var seconds = this.showSeconds ? now.getSeconds() : 0;
          var value = [hours, minutes, seconds].map(function (v) {
            return "00".concat(v || '').slice(-2);
          }).join(':');
          this.setAndClose(value);
        },
        onResetButton: function onResetButton() {
          this.setAndClose(this.resetValue);
        },
        onCloseButton: function onCloseButton() {
          this.$refs.control.hide(true);
        },
        onShow: function onShow() {
          this.isVisible = true;
        },
        onShown: function onShown() {
          var _this2 = this;
  
          this.$nextTick(function () {
            try {
              _this2.$refs.time.focus();
            } catch (_unused3) {}
          });
        },
        onHidden: function onHidden() {
          this.isVisible = false;
        },
        // Render function helpers
        defaultButtonFn: function defaultButtonFn(_ref) {
          var isHovered = _ref.isHovered,
              hasFocus = _ref.hasFocus;
          return this.$createElement(isHovered || hasFocus ? BIconClockFill : BIconClock, {
            props: {
              scale: 1.25
            },
            attrs: {
              'aria-hidden': 'true'
            }
          });
        }
      },
      render: function render(h) {
        var localHMS = this.localHMS;
        var disabled = this.disabled;
        var readonly = this.readonly;
        var placeholder = isUndefinedOrNull(this.placeholder) ? this.labelNoTimeSelected : this.placeholder; // Footer buttons
  
        var $footer = [];
  
        if (this.nowButton) {
          var label = this.labelNowButton;
          $footer.push(h(BButton, {
            staticClass: 'mx-1',
            props: {
              size: 'sm',
              disabled: disabled || readonly,
              variant: this.nowButtonVariant
            },
            attrs: {
              'aria-label': label || null
            },
            on: {
              click: this.onNowButton
            }
          }, label));
        }
  
        if (this.resetButton) {
          var _label = this.labelResetButton;
          $footer.push(h(BButton, {
            staticClass: 'mx-1',
            props: {
              size: 'sm',
              disabled: disabled || readonly,
              variant: this.resetButtonVariant
            },
            attrs: {
              'aria-label': _label || null
            },
            on: {
              click: this.onResetButton
            }
          }, _label));
        }
  
        if (!this.noCloseButton) {
          var _label2 = this.labelCloseButton;
          $footer.push(h(BButton, {
            staticClass: 'mx-1',
            props: {
              size: 'sm',
              disabled: disabled,
              variant: this.closeButtonVariant
            },
            attrs: {
              'aria-label': _label2 || null
            },
            on: {
              click: this.onCloseButton
            }
          }, _label2));
        }
  
        if ($footer.length > 0) {
          $footer = [h('div', {
            staticClass: 'b-form-date-controls d-flex flex-wrap mx-n1',
            class: {
              'justify-content-between': $footer.length > 1,
              'justify-content-end': $footer.length < 2
            }
          }, $footer)];
        }
  
        var $time = h(BTime, {
          ref: 'time',
          staticClass: 'b-form-time-control',
          props: this.timeProps,
          on: {
            input: this.onInput,
            context: this.onContext
          }
        }, $footer);
        return h(BVFormBtnLabelControl, {
          ref: 'control',
          staticClass: 'b-form-timepicker',
          props: _objectSpread2({}, this.$props, {
            // Overridden / computed props
            id: this.safeId(),
            rtl: this.isRTL,
            lang: this.computedLang,
            value: localHMS || '',
            formattedValue: localHMS ? this.formattedValue : '',
            placeholder: placeholder || ''
          }),
          on: {
            show: this.onShow,
            shown: this.onShown,
            hidden: this.onHidden
          },
          scopedSlots: {
            'button-content': this.$scopedSlots['button-content'] || this.defaultButtonFn
          }
        }, [$time]);
      }
    });
  
    var FormTimepickerPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BFormTimepicker: BFormTimepicker,
        BTimepicker: BFormTimepicker
      }
    });
  
    var ImagePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BImg: BImg,
        BImgLazy: BImgLazy
      }
    });
  
    var props$y = {
      tag: {
        type: String,
        default: 'div'
      }
    }; // @vue/component
  
    var BInputGroupText = /*#__PURE__*/Vue.extend({
      name: 'BInputGroupText',
      functional: true,
      props: props$y,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          staticClass: 'input-group-text'
        }), children);
      }
    });
  
    var commonProps$1 = {
      id: {
        type: String,
        default: null
      },
      tag: {
        type: String,
        default: 'div'
      },
      isText: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BInputGroupAddon = /*#__PURE__*/Vue.extend({
      name: 'BInputGroupAddon',
      functional: true,
      props: _objectSpread2({}, commonProps$1, {
        append: {
          type: Boolean,
          default: false
        }
      }),
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          class: {
            'input-group-append': props.append,
            'input-group-prepend': !props.append
          },
          attrs: {
            id: props.id
          }
        }), props.isText ? [h(BInputGroupText, children)] : children);
      }
    });
  
    var BInputGroupPrepend = /*#__PURE__*/Vue.extend({
      name: 'BInputGroupPrepend',
      functional: true,
      props: commonProps$1,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        // pass all our props/attrs down to child, and set`append` to false
        return h(BInputGroupAddon, a(data, {
          props: _objectSpread2({}, props, {
            append: false
          })
        }), children);
      }
    });
  
    var BInputGroupAppend = /*#__PURE__*/Vue.extend({
      name: 'BInputGroupAppend',
      functional: true,
      props: commonProps$1,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        // pass all our props/attrs down to child, and set`append` to true
        return h(BInputGroupAddon, a(data, {
          props: _objectSpread2({}, props, {
            append: true
          })
        }), children);
      }
    });
  
    var NAME$m = 'BInputGroup';
    var props$z = {
      id: {
        type: String
      },
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$m, 'size');
        }
      },
      prepend: {
        type: String
      },
      prependHtml: {
        type: String
      },
      append: {
        type: String
      },
      appendHtml: {
        type: String
      },
      tag: {
        type: String,
        default: 'div'
      }
    }; // @vue/component
  
    var BInputGroup = /*#__PURE__*/Vue.extend({
      name: NAME$m,
      functional: true,
      props: props$z,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots;
        var $slots = slots();
        var $scopedSlots = scopedSlots || {};
        var childNodes = []; // Prepend prop/slot
  
        if (props.prepend || props.prependHtml || hasNormalizedSlot('prepend', $scopedSlots, $slots)) {
          childNodes.push(h(BInputGroupPrepend, [// Prop
          props.prepend || props.prependHtml ? h(BInputGroupText, {
            domProps: htmlOrText(props.prependHtml, props.prepend)
          }) : h(), // Slot
          normalizeSlot('prepend', {}, $scopedSlots, $slots) || h()]));
        } else {
          childNodes.push(h());
        } // Default slot
  
  
        if (hasNormalizedSlot('default', $scopedSlots, $slots)) {
          childNodes.push.apply(childNodes, _toConsumableArray(normalizeSlot('default', {}, $scopedSlots, $slots)));
        } else {
          childNodes.push(h());
        } // Append prop
  
  
        if (props.append || props.appendHtml || hasNormalizedSlot('append', $scopedSlots, $slots)) {
          childNodes.push(h(BInputGroupAppend, [// prop
          props.append || props.appendHtml ? h(BInputGroupText, {
            domProps: htmlOrText(props.appendHtml, props.append)
          }) : h(), // Slot
          normalizeSlot('append', {}, $scopedSlots, $slots) || h()]));
        } else {
          childNodes.push(h());
        }
  
        return h(props.tag, a(data, {
          staticClass: 'input-group',
          class: _defineProperty({}, "input-group-".concat(props.size), props.size),
          attrs: {
            id: props.id || null,
            role: 'group'
          }
        }), childNodes);
      }
    });
  
    var InputGroupPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BInputGroup: BInputGroup,
        BInputGroupAddon: BInputGroupAddon,
        BInputGroupPrepend: BInputGroupPrepend,
        BInputGroupAppend: BInputGroupAppend,
        BInputGroupText: BInputGroupText
      }
    });
  
    var props$A = {
      tag: {
        type: String,
        default: 'div'
      },
      fluid: {
        // String breakpoint name new in Bootstrap v4.4.x
        type: [Boolean, String],
        default: false
      }
    }; // @vue/component
  
    var BContainer = /*#__PURE__*/Vue.extend({
      name: 'BContainer',
      functional: true,
      props: props$A,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          class: _defineProperty({
            container: !(props.fluid || props.fluid === ''),
            'container-fluid': props.fluid === true || props.fluid === ''
          }, "container-".concat(props.fluid), props.fluid && props.fluid !== true)
        }), children);
      }
    });
  
    var NAME$n = 'BJumbotron';
    var props$B = {
      fluid: {
        type: Boolean,
        default: false
      },
      containerFluid: {
        type: [Boolean, String],
        default: false
      },
      header: {
        type: String,
        default: null
      },
      headerHtml: {
        type: String,
        default: null
      },
      headerTag: {
        type: String,
        default: 'h1'
      },
      headerLevel: {
        type: [Number, String],
        default: '3'
      },
      lead: {
        type: String,
        default: null
      },
      leadHtml: {
        type: String,
        default: null
      },
      leadTag: {
        type: String,
        default: 'p'
      },
      tag: {
        type: String,
        default: 'div'
      },
      bgVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$n, 'bgVariant');
        }
      },
      borderVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$n, 'borderVariant');
        }
      },
      textVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$n, 'textVariant');
        }
      }
    }; // @vue/component
  
    var BJumbotron = /*#__PURE__*/Vue.extend({
      name: NAME$n,
      functional: true,
      props: props$B,
      render: function render(h, _ref) {
        var _class2;
  
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots;
        // The order of the conditionals matter.
        // We are building the component markup in order.
        var childNodes = [];
        var $slots = slots();
        var $scopedSlots = scopedSlots || {}; // Header
  
        if (props.header || hasNormalizedSlot('header', $scopedSlots, $slots) || props.headerHtml) {
          childNodes.push(h(props.headerTag, {
            class: _defineProperty({}, "display-".concat(props.headerLevel), props.headerLevel)
          }, normalizeSlot('header', {}, $scopedSlots, $slots) || props.headerHtml || stripTags(props.header)));
        } // Lead
  
  
        if (props.lead || hasNormalizedSlot('lead', $scopedSlots, $slots) || props.leadHtml) {
          childNodes.push(h(props.leadTag, {
            staticClass: 'lead'
          }, normalizeSlot('lead', {}, $scopedSlots, $slots) || props.leadHtml || stripTags(props.lead)));
        } // Default slot
  
  
        if (hasNormalizedSlot('default', $scopedSlots, $slots)) {
          childNodes.push(normalizeSlot('default', {}, $scopedSlots, $slots));
        } // If fluid, wrap content in a container/container-fluid
  
  
        if (props.fluid) {
          // Children become a child of a container
          childNodes = [h(BContainer, {
            props: {
              fluid: props.containerFluid
            }
          }, childNodes)];
        } // Return the jumbotron
  
  
        return h(props.tag, a(data, {
          staticClass: 'jumbotron',
          class: (_class2 = {
            'jumbotron-fluid': props.fluid
          }, _defineProperty(_class2, "text-".concat(props.textVariant), props.textVariant), _defineProperty(_class2, "bg-".concat(props.bgVariant), props.bgVariant), _defineProperty(_class2, "border-".concat(props.borderVariant), props.borderVariant), _defineProperty(_class2, "border", props.borderVariant), _class2)
        }), childNodes);
      }
    });
  
    var JumbotronPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BJumbotron: BJumbotron
      }
    });
  
    var COMMON_ALIGNMENT = ['start', 'end', 'center']; // Generates a prop object with a type of `[String, Number]`
  
    var strNum$1 = function strNum() {
      return {
        type: [String, Number],
        default: null
      };
    }; // Compute a `row-cols-{breakpoint}-{cols}` class name
    // Memoized function for better performance on generating class names
  
  
    var computeRowColsClass = memoize(function (breakpoint, cols) {
      cols = trim(toString$1(cols));
      return cols ? lowerCase(['row-cols', breakpoint, cols].filter(identity).join('-')) : null;
    }); // Get the breakpoint name from the `rowCols` prop name
    // Memoized function for better performance on extracting breakpoint names
  
    var computeRowColsBreakpoint = memoize(function (prop) {
      return lowerCase(prop.replace('cols', ''));
    }); // Cached copy of the `row-cols` breakpoint prop names
    // Will be populated when the props are generated
  
    var rowColsPropList = []; // Lazy evaled props factory for <b-row> (called only once,
    // the first time the component is used)
  
    var generateProps$2 = function generateProps() {
      // Grab the breakpoints from the cached config (including the '' (xs) breakpoint)
      var breakpoints = getBreakpointsUpCached(); // Supports classes like: `row-cols-2`, `row-cols-md-4`, `row-cols-xl-6`
  
      var rowColsProps = breakpoints.reduce(function (props, breakpoint) {
        props[suffixPropName(breakpoint, 'cols')] = strNum$1();
        return props;
      }, create(null)); // Cache the row-cols prop names
  
      rowColsPropList = keys(rowColsProps); // Return the generated props
  
      return _objectSpread2({
        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);
          }
        }
      }, rowColsProps);
    }; // We do not use `Vue.extend()` here as that would evaluate the props
    // immediately, which we do not want to happen
    // @vue/component
  
  
    var BRow = {
      name: 'BRow',
      functional: true,
  
      get props() {
        // Allow props to be lazy evaled on first access and
        // then they become a non-getter afterwards
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters
        delete this.props;
        this.props = generateProps$2();
        return this.props;
      },
  
      render: function render(h, _ref) {
        var _classList$push;
  
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var classList = []; // Loop through row-cols breakpoint props and generate the classes
  
        rowColsPropList.forEach(function (prop) {
          var c = computeRowColsClass(computeRowColsBreakpoint(prop), props[prop]); // If a class is returned, push it onto the array
  
          if (c) {
            classList.push(c);
          }
        });
        classList.push((_classList$push = {
          'no-gutters': props.noGutters
        }, _defineProperty(_classList$push, "align-items-".concat(props.alignV), props.alignV), _defineProperty(_classList$push, "justify-content-".concat(props.alignH), props.alignH), _defineProperty(_classList$push, "align-content-".concat(props.alignContent), props.alignContent), _classList$push));
        return h(props.tag, a(data, {
          staticClass: 'row',
          class: classList
        }), children);
      }
    };
  
    var LayoutPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BContainer: BContainer,
        BRow: BRow,
        BCol: BCol,
        BFormRow: BFormRow
      }
    });
  
    var LinkPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BLink: BLink
      }
    });
  
    var props$C = {
      tag: {
        type: String,
        default: 'div'
      },
      flush: {
        type: Boolean,
        default: false
      },
      horizontal: {
        type: [Boolean, String],
        default: false
      }
    }; // @vue/component
  
    var BListGroup = /*#__PURE__*/Vue.extend({
      name: 'BListGroup',
      functional: true,
      props: props$C,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var horizontal = props.horizontal === '' ? true : props.horizontal;
        horizontal = props.flush ? false : horizontal;
        var componentData = {
          staticClass: 'list-group',
          class: _defineProperty({
            'list-group-flush': props.flush,
            'list-group-horizontal': horizontal === true
          }, "list-group-horizontal-".concat(horizontal), isString(horizontal))
        };
        return h(props.tag, a(data, componentData), children);
      }
    });
  
    var NAME$o = 'BListGroupItem';
    var actionTags = ['a', 'router-link', 'button', 'b-link'];
    var linkProps$2 = propsFactory();
    delete linkProps$2.href.default;
    delete linkProps$2.to.default;
    var props$D = _objectSpread2({
      tag: {
        type: String,
        default: 'div'
      },
      action: {
        type: Boolean,
        default: null
      },
      button: {
        type: Boolean,
        default: null
      },
      variant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$o, 'variant');
        }
      }
    }, linkProps$2); // @vue/component
  
    var BListGroupItem = /*#__PURE__*/Vue.extend({
      name: NAME$o,
      functional: true,
      props: props$D,
      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 attrs = {};
        var itemProps = {};
  
        if (tag === 'button') {
          if (!data.attrs || !data.attrs.type) {
            // Add a type for button is one not provided in passed attributes
            attrs.type = 'button';
          }
  
          if (props.disabled) {
            // Set disabled attribute if button and disabled
            attrs.disabled = true;
          }
        } else {
          itemProps = pluckProps(linkProps$2, props);
        }
  
        var componentData = {
          attrs: attrs,
          props: itemProps,
          staticClass: 'list-group-item',
          class: (_class = {}, _defineProperty(_class, "list-group-item-".concat(props.variant), props.variant), _defineProperty(_class, 'list-group-item-action', isAction), _defineProperty(_class, "active", props.active), _defineProperty(_class, "disabled", props.disabled), _class)
        };
        return h(tag, a(data, componentData), children);
      }
    });
  
    var ListGroupPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BListGroup: BListGroup,
        BListGroupItem: BListGroupItem
      }
    });
  
    var props$E = {
      tag: {
        type: String,
        default: 'div'
      }
    }; // @vue/component
  
    var BMediaBody = /*#__PURE__*/Vue.extend({
      name: 'BMediaBody',
      functional: true,
      props: props$E,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          staticClass: 'media-body'
        }), children);
      }
    });
  
    var props$F = {
      tag: {
        type: String,
        default: 'div'
      },
      verticalAlign: {
        type: String,
        default: 'top'
      }
    }; // @vue/component
  
    var BMediaAside = /*#__PURE__*/Vue.extend({
      name: 'BMediaAside',
      functional: true,
      props: props$F,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var align = props.verticalAlign === 'top' ? 'start' : props.verticalAlign === 'bottom' ? 'end' : props.verticalAlign;
        return h(props.tag, a(data, {
          staticClass: 'd-flex',
          class: _defineProperty({}, "align-self-".concat(align), align)
        }), children);
      }
    });
  
    var props$G = {
      tag: {
        type: String,
        default: 'div'
      },
      rightAlign: {
        type: Boolean,
        default: false
      },
      verticalAlign: {
        type: String,
        default: 'top'
      },
      noBody: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BMedia = /*#__PURE__*/Vue.extend({
      name: 'BMedia',
      functional: true,
      props: props$G,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots,
            children = _ref.children;
        var childNodes = props.noBody ? children : [];
  
        if (!props.noBody) {
          var $slots = slots();
          var $scopedSlots = scopedSlots || {};
          var $aside = normalizeSlot('aside', {}, $scopedSlots, $slots);
          var $default = normalizeSlot('default', {}, $scopedSlots, $slots);
  
          if ($aside && !props.rightAlign) {
            childNodes.push(h(BMediaAside, {
              staticClass: 'mr-3',
              props: {
                verticalAlign: props.verticalAlign
              }
            }, $aside));
          }
  
          childNodes.push(h(BMediaBody, $default));
  
          if ($aside && props.rightAlign) {
            childNodes.push(h(BMediaAside, {
              staticClass: 'ml-3',
              props: {
                verticalAlign: props.verticalAlign
              }
            }, $aside));
          }
        }
  
        return h(props.tag, a(data, {
          staticClass: 'media'
        }), childNodes);
      }
    });
  
    var MediaPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BMedia: BMedia,
        BMediaAside: BMediaAside,
        BMediaBody: BMediaBody
      }
    });
  
    //
    // Single root node portaling of content, which retains parent/child hierarchy
    // Unlike Portal-Vue where portaled content is no longer a descendent of its
    // intended parent components
    //
    // Private components for use by Tooltips, Popovers and Modals
    //
    // Based on vue-simple-portal
    // https://github.com/LinusBorg/vue-simple-portal
    // Transporter target used by BTransporterSingle
    // Supports only a single root element
    // @vue/component
  
    var BTransporterTargetSingle = /*#__PURE__*/Vue.extend({
      // As an abstract component, it doesn't appear in the $parent chain of
      // components, which means the next parent of any component rendered inside
      // of this one will be the parent from which is was portal'd
      abstract: true,
      name: 'BTransporterTargetSingle',
      props: {
        nodes: {
          // Even though we only support a single root element,
          // VNodes are always passed as an array
          type: [Array, Function] // default: undefined
  
        }
      },
      data: function data(vm) {
        return {
          updatedNodes: vm.nodes
        };
      },
      destroyed: function destroyed() {
        removeNode(this.$el);
      },
      render: function render(h) {
        var nodes = isFunction(this.updatedNodes) ? this.updatedNodes({}) : this.updatedNodes;
        nodes = concat(nodes).filter(Boolean);
        /* istanbul ignore else */
  
        if (nodes && nodes.length > 0 && !nodes[0].text) {
          return nodes[0];
        } else {
          /* istanbul ignore next */
          return h();
        }
      }
    }); // This component has no root element, so only a single VNode is allowed
    // @vue/component
  
    var BTransporterSingle = /*#__PURE__*/Vue.extend({
      name: 'BTransporterSingle',
      mixins: [normalizeSlotMixin],
      props: {
        disabled: {
          type: Boolean,
          default: false
        },
        container: {
          // String: CSS selector,
          // HTMLElement: Element reference
          // Mainly needed for tooltips/popovers inside modals
          type: [String, HTMLElement],
          default: 'body'
        },
        tag: {
          // This should be set to match the root element type
          type: String,
          default: 'div'
        }
      },
      watch: {
        disabled: {
          immediate: true,
          handler: function handler(disabled) {
            disabled ? this.unmountTarget() : this.$nextTick(this.mountTarget);
          }
        }
      },
      created: function created() {
        this._bv_defaultFn = null;
        this._bv_target = null;
      },
      beforeMount: function beforeMount() {
        this.mountTarget();
      },
      updated: function updated() {
        // We need to make sure that all children have completed updating
        // before rendering in the target
        // `vue-simple-portal` has the this in a `$nextTick()`,
        // while `portal-vue` doesn't
        // Just trying to see if the `$nextTick()` delay is required or not
        // Since all slots in Vue 2.6.x are always functions
        this.updateTarget();
      },
      beforeDestroy: function beforeDestroy() {
        this.unmountTarget();
        this._bv_defaultFn = null;
      },
      methods: {
        // Get the element which the target should be appended to
        getContainer: function getContainer() {
          /* istanbul ignore else */
          if (isBrowser) {
            var container = this.container;
            return isString(container) ? select(container) : container;
          } else {
            return null;
          }
        },
        // Mount the target
        mountTarget: function mountTarget() {
          if (!this._bv_target) {
            var container = this.getContainer();
  
            if (container) {
              var el = document.createElement('div');
              container.appendChild(el);
              this._bv_target = new BTransporterTargetSingle({
                el: el,
                parent: this,
                propsData: {
                  // Initial nodes to be rendered
                  nodes: concat(this.normalizeSlot('default'))
                }
              });
            }
          }
        },
        // Update the content of the target
        updateTarget: function updateTarget() {
          if (isBrowser && this._bv_target) {
            var defaultFn = this.$scopedSlots.default;
  
            if (!this.disabled) {
              /* istanbul ignore else: only applicable in Vue 2.5.x */
              if (defaultFn && this._bv_defaultFn !== defaultFn) {
                // We only update the target component if the scoped slot
                // function is a fresh one. The new slot syntax (since Vue 2.6)
                // can cache unchanged slot functions and we want to respect that here
                this._bv_target.updatedNodes = defaultFn;
              } else if (!defaultFn) {
                // We also need to be back compatible with non-scoped default slot (i.e. 2.5.x)
                this._bv_target.updatedNodes = this.$slots.default;
              }
            } // Update the scoped slot function cache
  
  
            this._bv_defaultFn = defaultFn;
          }
        },
        // Unmount the target
        unmountTarget: function unmountTarget() {
          if (this._bv_target) {
            this._bv_target.$destroy();
  
            this._bv_target = null;
          }
        }
      },
      render: function render(h) {
        if (this.disabled) {
          var nodes = concat(this.normalizeSlot('default')).filter(identity);
  
          if (nodes.length > 0 && !nodes[0].text) {
            return nodes[0];
          }
        }
  
        return h();
      }
    });
  
    var PROP$1 = '$_bv_documentHandlers_'; // @vue/component
  
    var listenOnDocumentMixin = {
      created: function created() {
        var _this = this;
  
        /* istanbul ignore next */
        if (!isBrowser) {
          return;
        } // Declare non-reactive property
        // Object of arrays, keyed by event name,
        // where value is an array of handlers
        // Prop will be defined on client only
  
  
        this[PROP$1] = {}; // Set up our beforeDestroy handler (client only)
  
        this.$once('hook:beforeDestroy', function () {
          var items = _this[PROP$1] || {}; // Immediately delete this[PROP] to prevent the
          // listenOn/Off methods from running (which may occur
          // due to requestAnimationFrame/transition delays)
  
          delete _this[PROP$1]; // Remove all registered event handlers
  
          keys(items).forEach(function (evtName) {
            var handlers = items[evtName] || [];
            handlers.forEach(function (handler) {
              return eventOff(document, evtName, handler, EVENT_OPTIONS_NO_CAPTURE);
            });
          });
        });
      },
      methods: {
        listenDocument: function listenDocument(on, evtName, handler) {
          on ? this.listenOnDocument(evtName, handler) : this.listenOffDocument(evtName, handler);
        },
        listenOnDocument: function listenOnDocument(evtName, handler) {
          if (this[PROP$1] && isString(evtName) && isFunction(handler)) {
            this[PROP$1][evtName] = this[PROP$1][evtName] || [];
  
            if (!arrayIncludes(this[PROP$1][evtName], handler)) {
              this[PROP$1][evtName].push(handler);
              eventOn(document, evtName, handler, EVENT_OPTIONS_NO_CAPTURE);
            }
          }
        },
        listenOffDocument: function listenOffDocument(evtName, handler) {
          if (this[PROP$1] && isString(evtName) && isFunction(handler)) {
            eventOff(document, evtName, handler, EVENT_OPTIONS_NO_CAPTURE);
            this[PROP$1][evtName] = (this[PROP$1][evtName] || []).filter(function (h) {
              return h !== handler;
            });
          }
        }
      }
    };
  
    var PROP$2 = '$_bv_windowHandlers_'; // @vue/component
  
    var listenOnWindowMixin = {
      beforeCreate: function beforeCreate() {
        // Declare non-reactive property
        // Object of arrays, keyed by event name,
        // where value is an array of handlers
        this[PROP$2] = {};
      },
      beforeDestroy: function beforeDestroy() {
        if (isBrowser) {
          var items = this[PROP$2]; // Immediately delete this[PROP] to prevent the
          // listenOn/Off methods from running (which may occur
          // due to requestAnimationFrame delays)
  
          delete this[PROP$2]; // Remove all registered event handlers
  
          keys(items).forEach(function (evtName) {
            var handlers = items[evtName] || [];
            handlers.forEach(function (handler) {
              return eventOff(window, evtName, handler, EVENT_OPTIONS_NO_CAPTURE);
            });
          });
        }
      },
      methods: {
        listenWindow: function listenWindow(on, evtName, handler) {
          on ? this.listenOnWindow(evtName, handler) : this.listenOffWindow(evtName, handler);
        },
        listenOnWindow: function listenOnWindow(evtName, handler) {
          if (isBrowser && this[PROP$2] && isString(evtName) && isFunction(handler)) {
            this[PROP$2][evtName] = this[PROP$2][evtName] || [];
  
            if (!arrayIncludes(this[PROP$2][evtName], handler)) {
              this[PROP$2][evtName].push(handler);
              eventOn(window, evtName, handler, EVENT_OPTIONS_NO_CAPTURE);
            }
          }
        },
        listenOffWindow: function listenOffWindow(evtName, handler) {
          if (isBrowser && this[PROP$2] && isString(evtName) && isFunction(handler)) {
            eventOff(window, evtName, handler, EVENT_OPTIONS_NO_CAPTURE);
            this[PROP$2][evtName] = (this[PROP$2][evtName] || []).filter(function (h) {
              return h !== handler;
            });
          }
        }
      }
    };
  
    // This method returns a component's scoped style attribute name: `data-v-xxxxxxx`
    // The `_scopeId` options property is added by vue-loader when using scoped styles
    // and will be `undefined` if no scoped styles are in use
    var getScopeId = function getScopeId(vm) {
      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
      return vm ? vm.$options._scopeId || defaultValue : defaultValue;
    };
  
    var scopedStyleAttrsMixin = {
      computed: {
        scopedStyleAttrs: function scopedStyleAttrs() {
          var scopeId = getScopeId(this.$parent);
          return scopeId ? _defineProperty({}, scopeId, '') : {};
        }
      }
    };
  
    /**
     * Private ModalManager helper
     * Handles controlling modal stacking zIndexes and body adjustments/classes
     */
    // Default modal backdrop z-index
  
    var DEFAULT_ZINDEX = 1040; // Selectors for padding/margin adjustments
  
    var Selector$1 = {
      FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
      STICKY_CONTENT: '.sticky-top',
      NAVBAR_TOGGLER: '.navbar-toggler'
    }; // @vue/component
  
    var ModalManager = /*#__PURE__*/Vue.extend({
      data: function data() {
        return {
          modals: [],
          baseZIndex: null,
          scrollbarWidth: null,
          isBodyOverflowing: false
        };
      },
      computed: {
        modalCount: function modalCount() {
          return this.modals.length;
        },
        modalsAreOpen: function modalsAreOpen() {
          return this.modalCount > 0;
        }
      },
      watch: {
        modalCount: function modalCount(newCount, oldCount) {
          if (isBrowser) {
            this.getScrollbarWidth();
  
            if (newCount > 0 && oldCount === 0) {
              // Transitioning to modal(s) open
              this.checkScrollbar();
              this.setScrollbar();
              addClass(document.body, 'modal-open');
            } else if (newCount === 0 && oldCount > 0) {
              // Transitioning to modal(s) closed
              this.resetScrollbar();
              removeClass(document.body, 'modal-open');
            }
  
            setAttr(document.body, 'data-modal-open-count', String(newCount));
          }
        },
        modals: function modals(newVal) {
          var _this = this;
  
          this.checkScrollbar();
          requestAF(function () {
            _this.updateModals(newVal || []);
          });
        }
      },
      methods: {
        // Public methods
        registerModal: function registerModal(modal) {
          var _this2 = this;
  
          // Register the modal if not already registered
          if (modal && this.modals.indexOf(modal) === -1) {
            // Add modal to modals array
            this.modals.push(modal);
            modal.$once('hook:beforeDestroy', function () {
              _this2.unregisterModal(modal);
            });
          }
        },
        unregisterModal: function unregisterModal(modal) {
          var index = this.modals.indexOf(modal);
  
          if (index > -1) {
            // Remove modal from modals array
            this.modals.splice(index, 1); // Reset the modal's data
  
            if (!(modal._isBeingDestroyed || modal._isDestroyed)) {
              this.resetModal(modal);
            }
          }
        },
        getBaseZIndex: function getBaseZIndex() {
          if (isNull(this.baseZIndex) && isBrowser) {
            // Create a temporary `div.modal-backdrop` to get computed z-index
            var div = document.createElement('div');
            div.className = 'modal-backdrop d-none';
            div.style.display = 'none';
            document.body.appendChild(div);
            this.baseZIndex = toInteger(getCS(div).zIndex || DEFAULT_ZINDEX);
            document.body.removeChild(div);
          }
  
          return this.baseZIndex || DEFAULT_ZINDEX;
        },
        getScrollbarWidth: function getScrollbarWidth() {
          if (isNull(this.scrollbarWidth) && isBrowser) {
            // Create a temporary `div.measure-scrollbar` to get computed z-index
            var div = document.createElement('div');
            div.className = 'modal-scrollbar-measure';
            document.body.appendChild(div);
            this.scrollbarWidth = getBCR(div).width - div.clientWidth;
            document.body.removeChild(div);
          }
  
          return this.scrollbarWidth || 0;
        },
        // Private methods
        updateModals: function updateModals(modals) {
          var _this3 = this;
  
          var baseZIndex = this.getBaseZIndex();
          var scrollbarWidth = this.getScrollbarWidth();
          modals.forEach(function (modal, index) {
            // We update data values on each modal
            modal.zIndex = baseZIndex + index;
            modal.scrollbarWidth = scrollbarWidth;
            modal.isTop = index === _this3.modals.length - 1;
            modal.isBodyOverflowing = _this3.isBodyOverflowing;
          });
        },
        resetModal: function resetModal(modal) {
          if (modal) {
            modal.zIndex = this.getBaseZIndex();
            modal.isTop = true;
            modal.isBodyOverflowing = false;
          }
        },
        checkScrollbar: function checkScrollbar() {
          // Determine if the body element is overflowing
          var _getBCR = getBCR(document.body),
              left = _getBCR.left,
              right = _getBCR.right;
  
          this.isBodyOverflowing = left + right < window.innerWidth;
        },
        setScrollbar: function setScrollbar() {
          var body = document.body; // Storage place to cache changes to margins and padding
          // Note: This assumes the following element types are not added to the
          // document after the modal has opened.
  
          body._paddingChangedForModal = body._paddingChangedForModal || [];
          body._marginChangedForModal = body._marginChangedForModal || [];
  
          if (this.isBodyOverflowing) {
            var scrollbarWidth = this.scrollbarWidth; // Adjust fixed content padding
  
            /* istanbul ignore next: difficult to test in JSDOM */
  
            selectAll(Selector$1.FIXED_CONTENT).forEach(function (el) {
              var actualPadding = el.style.paddingRight;
              var calculatedPadding = getCS(el).paddingRight || 0;
              setAttr(el, 'data-padding-right', actualPadding);
              el.style.paddingRight = "".concat(toFloat(calculatedPadding) + scrollbarWidth, "px");
  
              body._paddingChangedForModal.push(el);
            }); // Adjust sticky content margin
  
            /* istanbul ignore next: difficult to test in JSDOM */
  
            selectAll(Selector$1.STICKY_CONTENT).forEach(function (el)
            /* istanbul ignore next */
            {
              var actualMargin = el.style.marginRight;
              var calculatedMargin = getCS(el).marginRight || 0;
              setAttr(el, 'data-margin-right', actualMargin);
              el.style.marginRight = "".concat(toFloat(calculatedMargin) - scrollbarWidth, "px");
  
              body._marginChangedForModal.push(el);
            }); // Adjust <b-navbar-toggler> margin
  
            /* istanbul ignore next: difficult to test in JSDOM */
  
            selectAll(Selector$1.NAVBAR_TOGGLER).forEach(function (el)
            /* istanbul ignore next */
            {
              var actualMargin = el.style.marginRight;
              var calculatedMargin = getCS(el).marginRight || 0;
              setAttr(el, 'data-margin-right', actualMargin);
              el.style.marginRight = "".concat(toFloat(calculatedMargin) + scrollbarWidth, "px");
  
              body._marginChangedForModal.push(el);
            }); // Adjust body padding
  
            var actualPadding = body.style.paddingRight;
            var calculatedPadding = getCS(body).paddingRight;
            setAttr(body, 'data-padding-right', actualPadding);
            body.style.paddingRight = "".concat(toFloat(calculatedPadding) + scrollbarWidth, "px");
          }
        },
        resetScrollbar: function resetScrollbar() {
          var body = document.body;
  
          if (body._paddingChangedForModal) {
            // Restore fixed content padding
            body._paddingChangedForModal.forEach(function (el) {
              /* istanbul ignore next: difficult to test in JSDOM */
              if (hasAttr(el, 'data-padding-right')) {
                el.style.paddingRight = getAttr(el, 'data-padding-right') || '';
                removeAttr(el, 'data-padding-right');
              }
            });
          }
  
          if (body._marginChangedForModal) {
            // Restore sticky content and navbar-toggler margin
            body._marginChangedForModal.forEach(function (el) {
              /* istanbul ignore next: difficult to test in JSDOM */
              if (hasAttr(el, 'data-margin-right')) {
                el.style.marginRight = getAttr(el, 'data-margin-right') || '';
                removeAttr(el, 'data-margin-right');
              }
            });
          }
  
          body._paddingChangedForModal = null;
          body._marginChangedForModal = null; // Restore body padding
  
          if (hasAttr(body, 'data-padding-right')) {
            body.style.paddingRight = getAttr(body, 'data-padding-right') || '';
            removeAttr(body, 'data-padding-right');
          }
        }
      }
    }); // Create and export our modal manager instance
  
    var modalManager = new ModalManager();
  
    var BvModalEvent = /*#__PURE__*/function (_BvEvent) {
      _inherits(BvModalEvent, _BvEvent);
  
      function BvModalEvent(type) {
        var _this;
  
        var eventInit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
        _classCallCheck(this, BvModalEvent);
  
        _this = _possibleConstructorReturn(this, _getPrototypeOf(BvModalEvent).call(this, type, eventInit)); // Freeze our new props as readonly, but leave them enumerable
  
        defineProperties(_assertThisInitialized(_this), {
          trigger: readonlyDescriptor()
        });
        return _this;
      }
  
      _createClass(BvModalEvent, null, [{
        key: "Defaults",
        get: function get() {
          return _objectSpread2({}, _get(_getPrototypeOf(BvModalEvent), "Defaults", this), {
            trigger: null
          });
        }
      }]);
  
      return BvModalEvent;
    }(BvEvent); // Named exports
  
    var NAME$p = 'BModal'; // ObserveDom config to detect changes in modal content
    // so that we can adjust the modal padding if needed
  
    var OBSERVER_CONFIG = {
      subtree: true,
      childList: true,
      characterData: true,
      attributes: true,
      attributeFilter: ['style', 'class']
    }; // Query selector to find all tabbable elements
    // (includes tabindex="-1", which we filter out after)
  
    var TABABLE_SELECTOR = ['button', '[href]:not(.disabled)', 'input', 'select', 'textarea', '[tabindex]', '[contenteditable]'].map(function (s) {
      return "".concat(s, ":not(:disabled):not([disabled])");
    }).join(', '); // --- Utility methods ---
    // Attempt to focus an element, and return true if successful
  
    var attemptFocus = function attemptFocus(el) {
      if (el && isVisible(el) && el.focus) {
        try {
          el.focus();
        } catch (_unused) {}
      } // If the element has focus, then return true
  
  
      return document.activeElement === el;
    }; // --- Props ---
  
  
    var props$H = {
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'size');
        }
      },
      centered: {
        type: Boolean,
        default: false
      },
      scrollable: {
        type: Boolean,
        default: false
      },
      buttonSize: {
        type: String,
        default: ''
      },
      noStacking: {
        type: Boolean,
        default: false
      },
      noFade: {
        type: Boolean,
        default: false
      },
      noCloseOnBackdrop: {
        type: Boolean,
        default: false
      },
      noCloseOnEsc: {
        type: Boolean,
        default: false
      },
      noEnforceFocus: {
        type: Boolean,
        default: false
      },
      ignoreEnforceFocusSelector: {
        type: [Array, String],
        default: ''
      },
      title: {
        type: String,
        default: ''
      },
      titleHtml: {
        type: String
      },
      titleTag: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'titleTag');
        }
      },
      titleClass: {
        type: [String, Array, Object],
        default: null
      },
      titleSrOnly: {
        type: Boolean,
        default: false
      },
      ariaLabel: {
        type: String,
        default: null
      },
      headerBgVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'headerBgVariant');
        }
      },
      headerBorderVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'headerBorderVariant');
        }
      },
      headerTextVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'headerTextVariant');
        }
      },
      headerCloseVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'headerCloseVariant');
        }
      },
      headerClass: {
        type: [String, Array, Object],
        default: null
      },
      bodyBgVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'bodyBgVariant');
        }
      },
      bodyTextVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'bodyTextVariant');
        }
      },
      modalClass: {
        type: [String, Array, Object],
        default: null
      },
      dialogClass: {
        type: [String, Array, Object],
        default: null
      },
      contentClass: {
        type: [String, Array, Object],
        default: null
      },
      bodyClass: {
        type: [String, Array, Object],
        default: null
      },
      footerBgVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'footerBgVariant');
        }
      },
      footerBorderVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'footerBorderVariant');
        }
      },
      footerTextVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'footerTextVariant');
        }
      },
      footerClass: {
        type: [String, Array, Object],
        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: {
        // HTML Element, CSS selector string or Vue component instance
        type: [HTMLElement, String, Object],
        default: null
      },
      headerCloseContent: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'headerCloseContent');
        }
      },
      headerCloseLabel: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'headerCloseLabel');
        }
      },
      cancelTitle: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'cancelTitle');
        }
      },
      cancelTitleHtml: {
        type: String
      },
      okTitle: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'okTitle');
        }
      },
      okTitleHtml: {
        type: String
      },
      cancelVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'cancelVariant');
        }
      },
      okVariant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$p, 'okVariant');
        }
      },
      lazy: {
        type: Boolean,
        default: false
      },
      busy: {
        type: Boolean,
        default: false
      },
      static: {
        type: Boolean,
        default: false
      },
      autoFocusButton: {
        type: String,
        default: null,
        validator: function validator(val) {
          /* istanbul ignore next */
          return isUndefinedOrNull(val) || arrayIncludes(['ok', 'cancel', 'close'], val);
        }
      }
    }; // @vue/component
  
    var BModal = /*#__PURE__*/Vue.extend({
      name: NAME$p,
      mixins: [idMixin, listenOnDocumentMixin, listenOnRootMixin, listenOnWindowMixin, normalizeSlotMixin, scopedStyleAttrsMixin],
      inheritAttrs: false,
      model: {
        prop: 'visible',
        event: 'change'
      },
      props: props$H,
      data: function data() {
        return {
          isHidden: true,
          // If modal should not be in document
          isVisible: false,
          // Controls modal visible state
          isTransitioning: false,
          // Used for style control
          isShow: false,
          // Used for style control
          isBlock: false,
          // Used for style control
          isOpening: false,
          // To signal that the modal is in the process of opening
          isClosing: false,
          // To signal that the modal is in the process of closing
          ignoreBackdropClick: false,
          // Used to signify if click out listener should ignore the click
          isModalOverflowing: false,
          return_focus: this.returnFocus || null,
          // The following items are controlled by the modalManager instance
          scrollbarWidth: 0,
          zIndex: modalManager.getBaseZIndex(),
          isTop: true,
          isBodyOverflowing: false
        };
      },
      computed: {
        modalClasses: function modalClasses() {
          return [{
            fade: !this.noFade,
            show: this.isShow
          }, this.modalClass];
        },
        modalStyles: function modalStyles() {
          var sbWidth = "".concat(this.scrollbarWidth, "px");
          return {
            paddingLeft: !this.isBodyOverflowing && this.isModalOverflowing ? sbWidth : '',
            paddingRight: this.isBodyOverflowing && !this.isModalOverflowing ? sbWidth : '',
            // Needed to fix issue https://github.com/bootstrap-vue/bootstrap-vue/issues/3457
            // Even though we are using v-show, we must ensure 'none' is restored in the styles
            display: this.isBlock ? 'block' : 'none'
          };
        },
        dialogClasses: function dialogClasses() {
          var _ref;
  
          return [(_ref = {}, _defineProperty(_ref, "modal-".concat(this.size), this.size), _defineProperty(_ref, 'modal-dialog-centered', this.centered), _defineProperty(_ref, 'modal-dialog-scrollable', this.scrollable), _ref), this.dialogClass];
        },
        headerClasses: function headerClasses() {
          var _ref2;
  
          return [(_ref2 = {}, _defineProperty(_ref2, "bg-".concat(this.headerBgVariant), this.headerBgVariant), _defineProperty(_ref2, "text-".concat(this.headerTextVariant), this.headerTextVariant), _defineProperty(_ref2, "border-".concat(this.headerBorderVariant), this.headerBorderVariant), _ref2), this.headerClass];
        },
        titleClasses: function titleClasses() {
          return [{
            'sr-only': this.titleSrOnly
          }, this.titleClass];
        },
        bodyClasses: function bodyClasses() {
          var _ref3;
  
          return [(_ref3 = {}, _defineProperty(_ref3, "bg-".concat(this.bodyBgVariant), this.bodyBgVariant), _defineProperty(_ref3, "text-".concat(this.bodyTextVariant), this.bodyTextVariant), _ref3), this.bodyClass];
        },
        footerClasses: function footerClasses() {
          var _ref4;
  
          return [(_ref4 = {}, _defineProperty(_ref4, "bg-".concat(this.footerBgVariant), this.footerBgVariant), _defineProperty(_ref4, "text-".concat(this.footerTextVariant), this.footerTextVariant), _defineProperty(_ref4, "border-".concat(this.footerBorderVariant), this.footerBorderVariant), _ref4), this.footerClass];
        },
        modalOuterStyle: function modalOuterStyle() {
          // Styles needed for proper stacking of modals
          return {
            position: 'absolute',
            zIndex: this.zIndex
          };
        },
        slotScope: function slotScope() {
          return {
            ok: this.onOk,
            cancel: this.onCancel,
            close: this.onClose,
            hide: this.hide,
            visible: this.isVisible
          };
        },
        computeIgnoreEnforceFocusSelector: function computeIgnoreEnforceFocusSelector() {
          // Normalize to an single selector with selectors separated by `,`
          return concat(this.ignoreEnforceFocusSelector).filter(identity).join(',').trim();
        }
      },
      watch: {
        visible: function visible(newVal, oldVal) {
          if (newVal !== oldVal) {
            this[newVal ? 'show' : 'hide']();
          }
        }
      },
      created: function created() {
        // Define non-reactive properties
        this._observer = null;
      },
      mounted: function mounted() {
        // Set initial z-index as queried from the DOM
        this.zIndex = modalManager.getBaseZIndex(); // Listen for events from others to either open or close ourselves
        // and listen to all modals to enable/disable enforce focus
  
        this.listenOnRoot('bv::show::modal', this.showHandler);
        this.listenOnRoot('bv::hide::modal', this.hideHandler);
        this.listenOnRoot('bv::toggle::modal', this.toggleHandler); // 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.$nextTick(this.show);
        }
      },
      beforeDestroy: function beforeDestroy() {
        // Ensure everything is back to normal
        if (this._observer) {
          this._observer.disconnect();
  
          this._observer = null;
        }
  
        if (this.isVisible) {
          this.isVisible = false;
          this.isShow = false;
          this.isTransitioning = false;
        }
      },
      methods: {
        // Private method to update the v-model
        updateModel: function updateModel(val) {
          if (val !== this.visible) {
            this.$emit('change', val);
          }
        },
        // Private method to create a BvModalEvent object
        buildEvent: function buildEvent(type) {
          var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
          return new BvModalEvent(type, _objectSpread2({
            // Default options
            cancelable: false,
            target: this.$refs.modal || this.$el || null,
            relatedTarget: null,
            trigger: null
          }, options, {
            // Options that can't be overridden
            vueTarget: this,
            componentId: this.safeId()
          }));
        },
        // Public method to show modal
        show: function show() {
          if (this.isVisible || this.isOpening) {
            // If already open, or in the process of opening, do nothing
  
            /* istanbul ignore next */
            return;
          }
          /* istanbul ignore next */
  
  
          if (this.isClosing) {
            // If we are in the process of closing, wait until hidden before re-opening
  
            /* istanbul ignore next */
            this.$once('hidden', this.show);
            /* istanbul ignore next */
  
            return;
          }
  
          this.isOpening = true; // Set the element to return focus to when closed
  
          this.return_focus = this.return_focus || this.getActiveElement();
          var showEvt = this.buildEvent('show', {
            cancelable: true
          });
          this.emitEvent(showEvt); // Don't show if canceled
  
          if (showEvt.defaultPrevented || this.isVisible) {
            this.isOpening = false; // Ensure the v-model reflects the current state
  
            this.updateModel(false);
            return;
          } // Show the modal
  
  
          this.doShow();
        },
        // Public method to hide modal
        hide: function hide() {
          var trigger = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  
          if (!this.isVisible || this.isClosing) {
            /* istanbul ignore next */
            return;
          }
  
          this.isClosing = true;
          var hideEvt = this.buildEvent('hide', {
            cancelable: trigger !== 'FORCE',
            trigger: trigger || null
          }); // We emit specific event for one of the three built-in buttons
  
          if (trigger === 'ok') {
            this.$emit('ok', hideEvt);
          } else if (trigger === 'cancel') {
            this.$emit('cancel', hideEvt);
          } else if (trigger === 'headerclose') {
            this.$emit('close', hideEvt);
          }
  
          this.emitEvent(hideEvt); // Hide if not canceled
  
          if (hideEvt.defaultPrevented || !this.isVisible) {
            this.isClosing = false; // Ensure v-model reflects current state
  
            this.updateModel(true);
            return;
          } // Stop observing for content changes
  
  
          if (this._observer) {
            this._observer.disconnect();
  
            this._observer = null;
          } // Trigger the hide transition
  
  
          this.isVisible = false; // Update the v-model
  
          this.updateModel(false);
        },
        // Public method to toggle modal visibility
        toggle: function toggle(triggerEl) {
          if (triggerEl) {
            this.return_focus = triggerEl;
          }
  
          if (this.isVisible) {
            this.hide('toggle');
          } else {
            this.show();
          }
        },
        // Private method to get the current document active element
        getActiveElement: function getActiveElement() {
          if (isBrowser) {
            var activeElement = document.activeElement; // Note: On IE 11, `document.activeElement` may be null.
            // So we test it for truthiness first.
            // https://github.com/bootstrap-vue/bootstrap-vue/issues/3206
            // Returning focus to document.body may cause unwanted scrolls, so we
            // exclude setting focus on body
  
            if (activeElement && activeElement !== document.body && activeElement.focus) {
              // Preset the fallback return focus value if it is not set
              // `document.activeElement` should be the trigger element that was clicked or
              // in the case of using the v-model, which ever element has current focus
              // Will be overridden by some commands such as toggle, etc.
              return activeElement;
            }
          }
  
          return null;
        },
        // Private method to get a list of all tabable elements within modal content
        getTabables: function getTabables() {
          // Find all tabable elements in the modal content
          // Assumes users have not used tabindex > 0 on elements!
          return selectAll(TABABLE_SELECTOR, this.$refs.content).filter(isVisible).filter(function (i) {
            return i.tabIndex > -1 && !i.disabled;
          });
        },
        // Private method to finish showing modal
        doShow: function doShow() {
          var _this = this;
  
          /* istanbul ignore next: commenting out for now until we can test stacking */
          if (modalManager.modalsAreOpen && this.noStacking) {
            // If another modal(s) is already open, wait for it(them) to close
            this.listenOnRootOnce('bv::modal::hidden', this.doShow);
            return;
          }
  
          modalManager.registerModal(this); // Place modal in DOM
  
          this.isHidden = false;
          this.$nextTick(function () {
            // We do this in `$nextTick()` to ensure the modal is in DOM first
            // before we show it
            _this.isVisible = true;
            _this.isOpening = false; // Update the v-model
  
            _this.updateModel(true);
  
            _this.$nextTick(function () {
              // In a nextTick in case modal content is lazy
              // Observe changes in modal content and adjust if necessary
              _this._observer = observeDom(_this.$refs.content, _this.checkModalOverflow.bind(_this), OBSERVER_CONFIG);
            });
          });
        },
        // Transition handlers
        onBeforeEnter: function onBeforeEnter() {
          this.isTransitioning = true;
          this.setResizeEvent(true);
        },
        onEnter: function onEnter() {
          var _this2 = this;
  
          this.isBlock = true; // We add the `show` class 1 frame later
          // `requestAF()` runs the callback before the next repaint, so we need
          // two calls to guarantee the next frame has been rendered
  
          requestAF(function () {
            requestAF(function () {
              _this2.isShow = true;
            });
          });
        },
        onAfterEnter: function onAfterEnter() {
          var _this3 = this;
  
          this.checkModalOverflow();
          this.isTransitioning = false; // We use `requestAF()` to allow transition hooks to complete
          // before passing control over to the other handlers
          // This will allow users to not have to use `$nextTick()` or `requestAF()`
          // when trying to pre-focus an element
  
          requestAF(function () {
            _this3.emitEvent(_this3.buildEvent('shown'));
  
            _this3.setEnforceFocus(true);
  
            _this3.$nextTick(function () {
              // Delayed in a `$nextTick()` to allow users time to pre-focus
              // an element if the wish
              _this3.focusFirst();
            });
          });
        },
        onBeforeLeave: function onBeforeLeave() {
          this.isTransitioning = true;
          this.setResizeEvent(false);
          this.setEnforceFocus(false);
        },
        onLeave: function onLeave() {
          // Remove the 'show' class
          this.isShow = false;
        },
        onAfterLeave: function onAfterLeave() {
          var _this4 = this;
  
          this.isBlock = false;
          this.isTransitioning = false;
          this.isModalOverflowing = false;
          this.isHidden = true;
          this.$nextTick(function () {
            _this4.isClosing = false;
            modalManager.unregisterModal(_this4);
  
            _this4.returnFocusTo(); // TODO: Need to find a way to pass the `trigger` property
            //       to the `hidden` event, not just only the `hide` event
  
  
            _this4.emitEvent(_this4.buildEvent('hidden'));
          });
        },
        // Event emitter
        emitEvent: function emitEvent(bvModalEvt) {
          var type = bvModalEvt.type; // We emit on root first incase a global listener wants to cancel
          // the event first before the instance emits its event
  
          this.emitOnRoot("bv::modal::".concat(type), bvModalEvt, bvModalEvt.componentId);
          this.$emit(type, bvModalEvt);
        },
        // UI event handlers
        onDialogMousedown: function onDialogMousedown() {
          var _this5 = this;
  
          // Watch to see if the matching mouseup event occurs outside the dialog
          // And if it does, cancel the clickOut handler
          var modal = this.$refs.modal;
  
          var onceModalMouseup = function onceModalMouseup(evt) {
            eventOff(modal, 'mouseup', onceModalMouseup, EVENT_OPTIONS_NO_CAPTURE);
  
            if (evt.target === modal) {
              _this5.ignoreBackdropClick = true;
            }
          };
  
          eventOn(modal, 'mouseup', onceModalMouseup, EVENT_OPTIONS_NO_CAPTURE);
        },
        onClickOut: function onClickOut(evt) {
          if (this.ignoreBackdropClick) {
            // Click was initiated inside the modal content, but finished outside.
            // Set by the above onDialogMousedown handler
            this.ignoreBackdropClick = false;
            return;
          } // Do nothing if not visible, backdrop click disabled, or element
          // that generated click event is no longer in document body
  
  
          if (!this.isVisible || this.noCloseOnBackdrop || !contains(document.body, evt.target)) {
            return;
          } // If backdrop clicked, hide modal
  
  
          if (!contains(this.$refs.content, evt.target)) {
            this.hide('backdrop');
          }
        },
        onOk: function onOk() {
          this.hide('ok');
        },
        onCancel: function onCancel() {
          this.hide('cancel');
        },
        onClose: function onClose() {
          this.hide('headerclose');
        },
        onEsc: function onEsc(evt) {
          // If ESC pressed, hide modal
          if (evt.keyCode === KEY_CODES.ESC && this.isVisible && !this.noCloseOnEsc) {
            this.hide('esc');
          }
        },
        // Document focusin listener
        focusHandler: function focusHandler(evt) {
          // If focus leaves modal content, bring it back
          var content = this.$refs.content;
          var target = evt.target;
  
          if (this.noEnforceFocus || !this.isTop || !this.isVisible || !content || document === target || contains(content, target) || this.computeIgnoreEnforceFocusSelector && closest(this.computeIgnoreEnforceFocusSelector, target, true)) {
            return;
          }
  
          var tabables = this.getTabables();
          var _this$$refs = this.$refs,
              bottomTrap = _this$$refs.bottomTrap,
              topTrap = _this$$refs.topTrap;
  
          if (bottomTrap && target === bottomTrap) {
            // If user pressed TAB out of modal into our bottom trab trap element
            // Find the first tabable element in the modal content and focus it
            if (attemptFocus(tabables[0])) {
              // Focus was successful
              return;
            }
          } else if (topTrap && target === topTrap) {
            // If user pressed CTRL-TAB out of modal and into our top tab trap element
            // Find the last tabable element in the modal content and focus it
            if (attemptFocus(tabables[tabables.length - 1])) {
              // Focus was successful
              return;
            }
          } // Otherwise focus the modal content container
  
  
          content.focus({
            preventScroll: true
          });
        },
        // Turn on/off focusin listener
        setEnforceFocus: function setEnforceFocus(on) {
          this.listenDocument(on, 'focusin', this.focusHandler);
        },
        // Resize listener
        setResizeEvent: function setResizeEvent(on) {
          this.listenWindow(on, 'resize', this.checkModalOverflow);
          this.listenWindow(on, 'orientationchange', this.checkModalOverflow);
        },
        // Root listener handlers
        showHandler: function showHandler(id, triggerEl) {
          if (id === this.safeId()) {
            this.return_focus = triggerEl || this.getActiveElement();
            this.show();
          }
        },
        hideHandler: function hideHandler(id) {
          if (id === this.safeId()) {
            this.hide('event');
          }
        },
        toggleHandler: function toggleHandler(id, triggerEl) {
          if (id === this.safeId()) {
            this.toggle(triggerEl);
          }
        },
        modalListener: function modalListener(bvEvt) {
          // If another modal opens, close this one if stacking not permitted
          if (this.noStacking && bvEvt.vueTarget !== this) {
            this.hide();
          }
        },
        // Focus control handlers
        focusFirst: function focusFirst() {
          var _this6 = this;
  
          // Don't try and focus if we are SSR
          if (isBrowser) {
            requestAF(function () {
              var modal = _this6.$refs.modal;
              var content = _this6.$refs.content;
  
              var activeElement = _this6.getActiveElement(); // If the modal contains the activeElement, we don't do anything
  
  
              if (modal && content && !(activeElement && contains(content, activeElement))) {
                var ok = _this6.$refs['ok-button'];
                var cancel = _this6.$refs['cancel-button'];
                var close = _this6.$refs['close-button']; // Focus the appropriate button or modal content wrapper
  
                var autoFocus = _this6.autoFocusButton;
                var el = autoFocus === 'ok' && ok ? ok.$el || ok : autoFocus === 'cancel' && cancel ? cancel.$el || cancel : autoFocus === 'close' && close ? close.$el || close : content; // Focus the element
  
                attemptFocus(el);
  
                if (el === content) {
                  // Make sure top of modal is showing (if longer than the viewport)
                  _this6.$nextTick(function () {
                    modal.scrollTop = 0;
                  });
                }
              }
            });
          }
        },
        returnFocusTo: function returnFocusTo() {
          // Prefer `returnFocus` prop over event specified
          // `return_focus` value
          var el = this.returnFocus || this.return_focus || null;
          this.return_focus = null;
          this.$nextTick(function () {
            // Is el a string CSS selector?
            el = isString(el) ? select(el) : el;
  
            if (el) {
              // Possibly could be a component reference
              el = el.$el || el;
              attemptFocus(el);
            }
          });
        },
        checkModalOverflow: function checkModalOverflow() {
          if (this.isVisible) {
            var modal = this.$refs.modal;
            this.isModalOverflowing = modal.scrollHeight > document.documentElement.clientHeight;
          }
        },
        makeModal: function makeModal(h) {
          // Modal header
          var header = h();
  
          if (!this.hideHeader) {
            var modalHeader = this.normalizeSlot('modal-header', this.slotScope);
  
            if (!modalHeader) {
              var closeButton = h();
  
              if (!this.hideHeaderClose) {
                closeButton = h(BButtonClose, {
                  ref: 'close-button',
                  props: {
                    content: this.headerCloseContent,
                    disabled: this.isTransitioning,
                    ariaLabel: this.headerCloseLabel,
                    textVariant: this.headerCloseVariant || this.headerTextVariant
                  },
                  on: {
                    click: this.onClose
                  }
                }, [this.normalizeSlot('modal-header-close')]);
              }
  
              var domProps = !this.hasNormalizedSlot('modal-title') && this.titleHtml ? {
                innerHTML: this.titleHtml
              } : {};
              modalHeader = [h(this.titleTag, {
                staticClass: 'modal-title',
                class: this.titleClasses,
                attrs: {
                  id: this.safeId('__BV_modal_title_')
                },
                domProps: domProps
              }, [this.normalizeSlot('modal-title', this.slotScope) || stripTags(this.title)]), closeButton];
            }
  
            header = h('header', {
              ref: 'header',
              staticClass: 'modal-header',
              class: this.headerClasses,
              attrs: {
                id: this.safeId('__BV_modal_header_')
              }
            }, [modalHeader]);
          } // Modal body
  
  
          var body = h('div', {
            ref: 'body',
            staticClass: 'modal-body',
            class: this.bodyClasses,
            attrs: {
              id: this.safeId('__BV_modal_body_')
            }
          }, this.normalizeSlot('default', this.slotScope)); // Modal footer
  
          var footer = h();
  
          if (!this.hideFooter) {
            var modalFooter = this.normalizeSlot('modal-footer', this.slotScope);
  
            if (!modalFooter) {
              var cancelButton = h();
  
              if (!this.okOnly) {
                var cancelHtml = this.cancelTitleHtml ? {
                  innerHTML: this.cancelTitleHtml
                } : null;
                cancelButton = h(BButton, {
                  ref: 'cancel-button',
                  props: {
                    variant: this.cancelVariant,
                    size: this.buttonSize,
                    disabled: this.cancelDisabled || this.busy || this.isTransitioning
                  },
                  on: {
                    click: this.onCancel
                  }
                }, [this.normalizeSlot('modal-cancel') || (cancelHtml ? h('span', {
                  domProps: cancelHtml
                }) : stripTags(this.cancelTitle))]);
              }
  
              var okHtml = this.okTitleHtml ? {
                innerHTML: this.okTitleHtml
              } : null;
              var okButton = h(BButton, {
                ref: 'ok-button',
                props: {
                  variant: this.okVariant,
                  size: this.buttonSize,
                  disabled: this.okDisabled || this.busy || this.isTransitioning
                },
                on: {
                  click: this.onOk
                }
              }, [this.normalizeSlot('modal-ok') || (okHtml ? h('span', {
                domProps: okHtml
              }) : stripTags(this.okTitle))]);
              modalFooter = [cancelButton, okButton];
            }
  
            footer = h('footer', {
              ref: 'footer',
              staticClass: 'modal-footer',
              class: this.footerClasses,
              attrs: {
                id: this.safeId('__BV_modal_footer_')
              }
            }, [modalFooter]);
          } // Assemble modal content
  
  
          var modalContent = h('div', {
            ref: 'content',
            staticClass: 'modal-content',
            class: this.contentClass,
            attrs: {
              role: 'document',
              id: this.safeId('__BV_modal_content_'),
              tabindex: '-1'
            }
          }, [header, body, footer]); // Tab trap to prevent page from scrolling to next element in
          // tab index during enforce focus tab cycle
  
          var tabTrapTop = h();
          var tabTrapBottom = h();
  
          if (this.isVisible && !this.noEnforceFocus) {
            tabTrapTop = h('span', {
              ref: 'topTrap',
              attrs: {
                tabindex: '0'
              }
            });
            tabTrapBottom = h('span', {
              ref: 'bottomTrap',
              attrs: {
                tabindex: '0'
              }
            });
          } // Modal dialog wrapper
  
  
          var modalDialog = h('div', {
            ref: 'dialog',
            staticClass: 'modal-dialog',
            class: this.dialogClasses,
            on: {
              mousedown: this.onDialogMousedown
            }
          }, [tabTrapTop, modalContent, tabTrapBottom]); // Modal
  
          var modal = h('div', {
            ref: 'modal',
            staticClass: 'modal',
            class: this.modalClasses,
            style: this.modalStyles,
            directives: [{
              name: 'show',
              rawName: 'v-show',
              value: this.isVisible,
              expression: 'isVisible'
            }],
            attrs: {
              id: this.safeId(),
              role: 'dialog',
              'aria-hidden': this.isVisible ? null : 'true',
              'aria-modal': this.isVisible ? 'true' : null,
              'aria-label': this.ariaLabel,
              'aria-labelledby': this.hideHeader || this.ariaLabel || !(this.hasNormalizedSlot('modal-title') || this.titleHtml || this.title) ? null : this.safeId('__BV_modal_title_'),
              'aria-describedby': this.safeId('__BV_modal_body_')
            },
            on: {
              keydown: this.onEsc,
              click: this.onClickOut
            }
          }, [modalDialog]); // Wrap modal in transition
          // Sadly, we can't use BVTransition here due to the differences in
          // transition durations for .modal and .modal-dialog. Not until
          // issue https://github.com/vuejs/vue/issues/9986 is resolved
  
          modal = h('transition', {
            props: {
              enterClass: '',
              enterToClass: '',
              enterActiveClass: '',
              leaveClass: '',
              leaveActiveClass: '',
              leaveToClass: ''
            },
            on: {
              beforeEnter: this.onBeforeEnter,
              enter: this.onEnter,
              afterEnter: this.onAfterEnter,
              beforeLeave: this.onBeforeLeave,
              leave: this.onLeave,
              afterLeave: this.onAfterLeave
            }
          }, [modal]); // Modal backdrop
  
          var backdrop = h();
  
          if (!this.hideBackdrop && this.isVisible) {
            backdrop = h('div', {
              staticClass: 'modal-backdrop',
              attrs: {
                id: this.safeId('__BV_modal_backdrop_')
              }
            }, [this.normalizeSlot('modal-backdrop')]);
          }
  
          backdrop = h(BVTransition, {
            props: {
              noFade: this.noFade
            }
          }, [backdrop]); // If the parent has a scoped style attribute, and the modal
          // is portalled, add the scoped attribute to the modal wrapper
  
          var scopedStyleAttrs = !this.static ? this.scopedStyleAttrs : {}; // Assemble modal and backdrop in an outer <div>
  
          return h('div', {
            key: "modal-outer-".concat(this._uid),
            style: this.modalOuterStyle,
            attrs: _objectSpread2({}, scopedStyleAttrs, {}, this.$attrs, {
              id: this.safeId('__BV_modal_outer_')
            })
          }, [modal, backdrop]);
        }
      },
      render: function render(h) {
        if (this.static) {
          return this.lazy && this.isHidden ? h() : this.makeModal(h);
        } else {
          return this.isHidden ? h() : h(BTransporterSingle, [this.makeModal(h)]);
        }
      }
    });
  
    var EVENT_SHOW = 'bv::show::modal'; // Prop name we use to store info on root element
  
    var PROPERTY = '__bv_modal_directive__';
  
    var getTarget = function getTarget(_ref) {
      var _ref$modifiers = _ref.modifiers,
          modifiers = _ref$modifiers === void 0 ? {} : _ref$modifiers,
          arg = _ref.arg,
          value = _ref.value;
      // Try value, then arg, otherwise pick last modifier
      return isString(value) ? value : isString(arg) ? arg : keys(modifiers).reverse()[0];
    };
  
    var getTriggerElement = function getTriggerElement(el) {
      // If root element is a dropdown-item or nav-item, we
      // need to target the inner link or button instead
      return el && matches(el, '.dropdown-menu > li, li.nav-item') ? select('a, button', el) || el : el;
    };
  
    var setRole = function setRole(trigger) {
      // Ensure accessibility on non button elements
      if (trigger && trigger.tagName !== 'BUTTON') {
        // Only set a role if the trigger element doesn't have one
        if (!hasAttr(trigger, 'role')) {
          setAttr(trigger, 'role', 'button');
        } // Add a tabindex is not a button or link, and tabindex is not provided
  
  
        if (trigger.tagName !== 'A' && !hasAttr(trigger, 'tabindex')) {
          setAttr(trigger, 'tabindex', '0');
        }
      }
    };
  
    var bind$1 = function bind(el, binding, vnode) {
      var target = getTarget(binding);
      var trigger = getTriggerElement(el);
  
      if (target && trigger) {
        var handler = function handler(evt) {
          // `currentTarget` is the element with the listener on it
          var currentTarget = evt.currentTarget;
  
          if (!isDisabled(currentTarget)) {
            var type = evt.type;
            var key = evt.keyCode; // Open modal only if trigger is not disabled
  
            if (type === 'click' || type === 'keydown' && (key === KEY_CODES.ENTER || key === KEY_CODES.SPACE)) {
              vnode.context.$root.$emit(EVENT_SHOW, target, currentTarget);
            }
          }
        };
  
        el[PROPERTY] = {
          handler: handler,
          target: target,
          trigger: trigger
        }; // If element is not a button, we add `role="button"` for accessibility
  
        setRole(trigger); // Listen for click events
  
        eventOn(trigger, 'click', handler, EVENT_OPTIONS_PASSIVE);
  
        if (trigger.tagName !== 'BUTTON' && getAttr(trigger, 'role') === 'button') {
          // If trigger isn't a button but has role button,
          // we also listen for `keydown.space` && `keydown.enter`
          eventOn(trigger, 'keydown', handler, EVENT_OPTIONS_PASSIVE);
        }
      }
    };
  
    var unbind$1 = function unbind(el) {
      var oldProp = el[PROPERTY] || {};
      var trigger = oldProp.trigger;
      var handler = oldProp.handler;
  
      if (trigger && handler) {
        eventOff(trigger, 'click', handler, EVENT_OPTIONS_PASSIVE);
        eventOff(trigger, 'keydown', handler, EVENT_OPTIONS_PASSIVE);
        eventOff(el, 'click', handler, EVENT_OPTIONS_PASSIVE);
        eventOff(el, 'keydown', handler, EVENT_OPTIONS_PASSIVE);
      }
  
      delete el[PROPERTY];
    };
  
    var componentUpdated$1 = function componentUpdated(el, binding, vnode) {
      var oldProp = el[PROPERTY] || {};
      var target = getTarget(binding);
      var trigger = getTriggerElement(el);
  
      if (target !== oldProp.target || trigger !== oldProp.trigger) {
        // We bind and rebind if the target or trigger changes
        unbind$1(el);
        bind$1(el, binding, vnode);
      } // If trigger element is not a button, ensure `role="button"`
      // is still set for accessibility
  
  
      setRole(trigger);
    };
  
    var updated = function updated() {};
    /*
     * Export our directive
     */
  
  
    var VBModal = {
      inserted: componentUpdated$1,
      updated: updated,
      componentUpdated: componentUpdated$1,
      unbind: unbind$1
    };
  
    var PROP_NAME$2 = '$bvModal';
    var PROP_NAME_PRIV = '_bv__modal'; // Base modal props that are allowed
    // Some may be ignored or overridden on some message boxes
    // Prop ID is allowed, but really only should be used for testing
    // We need to add it in explicitly as it comes from the `idMixin`
  
    var BASE_PROPS = ['id'].concat(_toConsumableArray(keys(omit(props$H, ['busy', 'lazy', 'noStacking', "static", 'visible'])))); // Fallback event resolver (returns undefined)
  
    var defaultResolver = function defaultResolver() {}; // Map prop names to modal slot names
  
  
    var propsToSlots = {
      msgBoxContent: 'default',
      title: 'modal-title',
      okTitle: 'modal-ok',
      cancelTitle: 'modal-cancel'
    }; // --- Utility methods ---
    // Method to filter only recognized props that are not undefined
  
    var filterOptions = function filterOptions(options) {
      return BASE_PROPS.reduce(function (memo, key) {
        if (!isUndefined(options[key])) {
          memo[key] = options[key];
        }
  
        return memo;
      }, {});
    }; // Method to install `$bvModal` VM injection
  
  
    var plugin = function plugin(Vue) {
      // Create a private sub-component that extends BModal
      // which self-destructs after hidden
      // @vue/component
      var BMsgBox = Vue.extend({
        name: 'BMsgBox',
        extends: BModal,
        destroyed: function destroyed() {
          // Make sure we not in document any more
          if (this.$el && this.$el.parentNode) {
            this.$el.parentNode.removeChild(this.$el);
          }
        },
        mounted: function mounted() {
          var _this = this;
  
          // Self destruct handler
          var handleDestroy = function handleDestroy() {
            var self = _this;
  
            _this.$nextTick(function () {
              // In a `setTimeout()` to release control back to application
              setTimeout(function () {
                return self.$destroy();
              }, 0);
            });
          }; // Self destruct if parent destroyed
  
  
          this.$parent.$once('hook:destroyed', handleDestroy); // Self destruct after hidden
  
          this.$once('hidden', handleDestroy); // Self destruct on route change
  
          /* istanbul ignore if */
  
          if (this.$router && this.$route) {
            // Destroy ourselves if route changes
  
            /* istanbul ignore next */
            this.$once('hook:beforeDestroy', this.$watch('$router', handleDestroy));
          } // Show the `BMsgBox`
  
  
          this.show();
        }
      }); // Method to generate the on-demand modal message box
      // Returns a promise that resolves to a value returned by the resolve
  
      var asyncMsgBox = function asyncMsgBox($parent, props) {
        var resolver = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultResolver;
  
        if (warnNotClient(PROP_NAME$2) || warnNoPromiseSupport(PROP_NAME$2)) {
          /* istanbul ignore next */
          return;
        } // Create an instance of `BMsgBox` component
  
  
        var msgBox = new BMsgBox({
          // We set parent as the local VM so these modals can emit events on
          // the app `$root`, as needed by things like tooltips and popovers
          // And it helps to ensure `BMsgBox` is destroyed when parent is destroyed
          parent: $parent,
          // Preset the prop values
          propsData: _objectSpread2({}, filterOptions(getComponentConfig('BModal') || {}), {
            // Defaults that user can override
            hideHeaderClose: true,
            hideHeader: !(props.title || props.titleHtml)
          }, omit(props, keys(propsToSlots)), {
            // Props that can't be overridden
            lazy: false,
            busy: false,
            visible: false,
            noStacking: false,
            noEnforceFocus: false
          })
        }); // Convert certain props to scoped slots
  
        keys(propsToSlots).forEach(function (prop) {
          if (!isUndefined(props[prop])) {
            // Can be a string, or array of VNodes.
            // Alternatively, user can use HTML version of prop to pass an HTML string.
            msgBox.$slots[propsToSlots[prop]] = concat(props[prop]);
          }
        }); // Return a promise that resolves when hidden, or rejects on destroyed
  
        return new Promise(function (resolve, reject) {
          var resolved = false;
          msgBox.$once('hook:destroyed', function () {
            if (!resolved) {
              /* istanbul ignore next */
              reject(new Error('BootstrapVue MsgBox destroyed before resolve'));
            }
          });
          msgBox.$on('hide', function (bvModalEvt) {
            if (!bvModalEvt.defaultPrevented) {
              var result = resolver(bvModalEvt); // If resolver didn't cancel hide, we resolve
  
              if (!bvModalEvt.defaultPrevented) {
                resolved = true;
                resolve(result);
              }
            }
          }); // Create a mount point (a DIV) and mount the msgBo which will trigger it to show
  
          var div = document.createElement('div');
          document.body.appendChild(div);
          msgBox.$mount(div);
        });
      }; // Private utility method to open a user defined message box and returns a promise.
      // Not to be used directly by consumers, as this method may change calling syntax
  
  
      var makeMsgBox = function makeMsgBox($parent, content) {
        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
        var resolver = arguments.length > 3 ? arguments[3] : undefined;
  
        if (!content || warnNoPromiseSupport(PROP_NAME$2) || warnNotClient(PROP_NAME$2) || !isFunction(resolver)) {
          /* istanbul ignore next */
          return;
        }
  
        return asyncMsgBox($parent, _objectSpread2({}, filterOptions(options), {
          msgBoxContent: content
        }), resolver);
      }; // BvModal instance class
  
  
      var BvModal = /*#__PURE__*/function () {
        function BvModal(vm) {
          _classCallCheck(this, BvModal);
  
          // Assign the new properties to this instance
          assign(this, {
            _vm: vm,
            _root: vm.$root
          }); // Set these properties as read-only and non-enumerable
  
          defineProperties(this, {
            _vm: readonlyDescriptor(),
            _root: readonlyDescriptor()
          });
        } // --- Instance methods ---
        // Show modal with the specified ID args are for future use
  
  
        _createClass(BvModal, [{
          key: "show",
          value: function show(id) {
            if (id && this._root) {
              var _this$_root;
  
              for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
                args[_key - 1] = arguments[_key];
              }
  
              (_this$_root = this._root).$emit.apply(_this$_root, ['bv::show::modal', id].concat(args));
            }
          } // Hide modal with the specified ID args are for future use
  
        }, {
          key: "hide",
          value: function hide(id) {
            if (id && this._root) {
              var _this$_root2;
  
              for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
                args[_key2 - 1] = arguments[_key2];
              }
  
              (_this$_root2 = this._root).$emit.apply(_this$_root2, ['bv::hide::modal', id].concat(args));
            }
          } // The following methods require Promise support!
          // IE 11 and others do not support Promise natively, so users
          // should have a Polyfill loaded (which they need anyways for IE 11 support)
          // Open a message box with OK button only and returns a promise
  
        }, {
          key: "msgBoxOk",
          value: function msgBoxOk(message) {
            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
            // Pick the modal props we support from options
            var props = _objectSpread2({}, options, {
              // Add in overrides and our content prop
              okOnly: true,
              okDisabled: false,
              hideFooter: false,
              msgBoxContent: message
            });
  
            return makeMsgBox(this._vm, message, props, function () {
              // Always resolve to true for OK
              return true;
            });
          } // Open a message box modal with OK and CANCEL buttons
          // and returns a promise
  
        }, {
          key: "msgBoxConfirm",
          value: function msgBoxConfirm(message) {
            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
            // Set the modal props we support from options
            var props = _objectSpread2({}, options, {
              // Add in overrides and our content prop
              okOnly: false,
              okDisabled: false,
              cancelDisabled: false,
              hideFooter: false
            });
  
            return makeMsgBox(this._vm, message, props, function (bvModalEvt) {
              var trigger = bvModalEvt.trigger;
              return trigger === 'ok' ? true : trigger === 'cancel' ? false : null;
            });
          }
        }]);
  
        return BvModal;
      }(); // Add our instance mixin
  
  
      Vue.mixin({
        beforeCreate: function beforeCreate() {
          // Because we need access to `$root` for `$emits`, and VM for parenting,
          // we have to create a fresh instance of `BvModal` for each VM
          this[PROP_NAME_PRIV] = new BvModal(this);
        }
      }); // Define our read-only `$bvModal` instance property
      // Placed in an if just in case in HMR mode
      // eslint-disable-next-line no-prototype-builtins
  
      if (!Vue.prototype.hasOwnProperty(PROP_NAME$2)) {
        defineProperty(Vue.prototype, PROP_NAME$2, {
          get: function get() {
            /* istanbul ignore next */
            if (!this || !this[PROP_NAME_PRIV]) {
              warn("\"".concat(PROP_NAME$2, "\" must be accessed from a Vue instance \"this\" context."), 'BModal');
            }
  
            return this[PROP_NAME_PRIV];
          }
        });
      }
    };
  
    var BVModalPlugin = /*#__PURE__*/pluginFactory({
      plugins: {
        plugin: plugin
      }
    });
  
    var ModalPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BModal: BModal
      },
      directives: {
        VBModal: VBModal
      },
      // $bvModal injection
      plugins: {
        BVModalPlugin: BVModalPlugin
      }
    });
  
    var props$I = {
      tag: {
        type: String,
        default: 'ul'
      },
      fill: {
        type: Boolean,
        default: false
      },
      justified: {
        type: Boolean,
        default: false
      },
      align: {
        type: String,
        default: null
      },
      tabs: {
        type: Boolean,
        default: false
      },
      pills: {
        type: Boolean,
        default: false
      },
      vertical: {
        type: Boolean,
        default: false
      },
      small: {
        type: Boolean,
        default: false
      },
      cardHeader: {
        // Set to true if placing in a card header
        type: Boolean,
        default: false
      }
    }; // -- Utils --
  
    var computeJustifyContent = function computeJustifyContent(value) {
      // Normalize value
      value = value === 'left' ? 'start' : value === 'right' ? 'end' : value;
      return "justify-content-".concat(value);
    }; // @vue/component
  
  
    var BNav = /*#__PURE__*/Vue.extend({
      name: 'BNav',
      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, a(data, {
          staticClass: 'nav',
          class: (_class = {
            'nav-tabs': props.tabs,
            'nav-pills': props.pills && !props.tabs,
            'card-header-tabs': !props.vertical && props.cardHeader && props.tabs,
            'card-header-pills': !props.vertical && props.cardHeader && props.pills && !props.tabs,
            'flex-column': props.vertical,
            'nav-fill': !props.vertical && props.fill,
            'nav-justified': !props.vertical && props.justified
          }, _defineProperty(_class, computeJustifyContent(props.align), !props.vertical && props.align), _defineProperty(_class, "small", props.small), _class)
        }), children);
      }
    });
  
    var props$J = propsFactory(); // @vue/component
  
    var BNavItem = /*#__PURE__*/Vue.extend({
      name: 'BNavItem',
      functional: true,
      props: _objectSpread2({}, props$J, {
        linkAttrs: {
          type: Object,
          default: function _default() {}
        },
        linkClasses: {
          type: [String, Object, Array],
          default: null
        }
      }),
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            listeners = _ref.listeners,
            children = _ref.children;
        // We transfer the listeners to the link
        delete data.on;
        return h('li', a(data, {
          staticClass: 'nav-item'
        }), [h(BLink, {
          staticClass: 'nav-link',
          class: props.linkClasses,
          attrs: props.linkAttrs,
          props: props,
          on: listeners
        }, children)]);
      }
    });
  
    var props$K = {}; // @vue/component
  
    var BNavText = /*#__PURE__*/Vue.extend({
      name: 'BNavText',
      functional: true,
      props: props$K,
      render: function render(h, _ref) {
        var data = _ref.data,
            children = _ref.children;
        return h('li', a(data, {
          staticClass: 'navbar-text'
        }), children);
      }
    });
  
    var props$L = _objectSpread2({}, omit(props$o, ['inline']), {
      formClass: {
        type: [String, Array, Object],
        default: null
      }
    }); // @vue/component
  
    var BNavForm = /*#__PURE__*/Vue.extend({
      name: 'BNavForm',
      functional: true,
      props: props$L,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children,
            _ref$listeners = _ref.listeners,
            listeners = _ref$listeners === void 0 ? {} : _ref$listeners;
        var attrs = data.attrs; // The following data properties are cleared out
        // as they will be passed to BForm directly
  
        data.attrs = {};
        data.on = {};
        var $form = h(BForm, {
          class: props.formClass,
          props: _objectSpread2({}, props, {
            inline: true
          }),
          attrs: attrs,
          on: listeners
        }, children);
        return h('li', a(data, {
          staticClass: 'form-inline'
        }), [$form]);
      }
    });
  
    var props$M = pluckProps(['text', 'html', 'menuClass', 'toggleClass', 'noCaret', 'role', 'lazy'], props$j); // @vue/component
  
    var BNavItemDropdown = /*#__PURE__*/Vue.extend({
      name: 'BNavItemDropdown',
      mixins: [idMixin, dropdownMixin, normalizeSlotMixin],
      props: props$M,
      computed: {
        isNav: function isNav() {
          // Signal to dropdown mixin that we are in a navbar
          return true;
        },
        dropdownClasses: function dropdownClasses() {
          return [this.directionClass, {
            show: this.visible
          }];
        },
        menuClasses: function menuClasses() {
          return [this.menuClass, {
            'dropdown-menu-right': this.right,
            show: this.visible
          }];
        },
        toggleClasses: function toggleClasses() {
          return [this.toggleClass, {
            'dropdown-toggle-no-caret': this.noCaret
          }];
        }
      },
      render: function render(h) {
        var button = h(BLink, {
          ref: 'toggle',
          staticClass: 'nav-link dropdown-toggle',
          class: this.toggleClasses,
          props: {
            href: '#',
            disabled: this.disabled
          },
          attrs: {
            id: this.safeId('_BV_button_'),
            'aria-haspopup': 'true',
            'aria-expanded': this.visible ? 'true' : 'false'
          },
          on: {
            mousedown: this.onMousedown,
            click: this.toggle,
            keydown: this.toggle // Handle ENTER, SPACE and DOWN
  
          }
        }, [this.$slots['button-content'] || this.$slots.text || h('span', {
          domProps: htmlOrText(this.html, this.text)
        })]);
        var menu = h('ul', {
          staticClass: 'dropdown-menu',
          class: this.menuClasses,
          ref: 'menu',
          attrs: {
            tabindex: '-1',
            'aria-labelledby': this.safeId('_BV_button_')
          },
          on: {
            keydown: this.onKeydown // Handle UP, DOWN and ESC
  
          }
        }, !this.lazy || this.visible ? this.normalizeSlot('default', {
          hide: this.hide
        }) : [h()]);
        return h('li', {
          staticClass: 'nav-item b-nav-dropdown dropdown',
          class: this.dropdownClasses,
          attrs: {
            id: this.safeId()
          }
        }, [button, menu]);
      }
    });
  
    var NavPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BNav: BNav,
        BNavItem: BNavItem,
        BNavText: BNavText,
        BNavForm: BNavForm,
        BNavItemDropdown: BNavItemDropdown,
        BNavItemDd: BNavItemDropdown,
        BNavDropdown: BNavItemDropdown,
        BNavDd: BNavItemDropdown
      },
      plugins: {
        DropdownPlugin: DropdownPlugin
      }
    });
  
    var NAME$q = 'BNavbar';
    var props$N = {
      tag: {
        type: String,
        default: 'nav'
      },
      type: {
        type: String,
        default: 'light'
      },
      variant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$q, 'variant');
        }
      },
      toggleable: {
        type: [Boolean, String],
        default: false
      },
      fixed: {
        type: String
      },
      sticky: {
        type: Boolean,
        default: false
      },
      print: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BNavbar = /*#__PURE__*/Vue.extend({
      name: NAME$q,
      mixins: [normalizeSlotMixin],
      props: props$N,
      provide: function provide() {
        return {
          bvNavbar: this
        };
      },
      computed: {
        breakpointClass: function breakpointClass() {
          var breakpoint = null;
          var xs = getBreakpoints()[0];
          var toggleable = this.toggleable;
  
          if (toggleable && isString(toggleable) && toggleable !== xs) {
            breakpoint = "navbar-expand-".concat(toggleable);
          } else if (toggleable === false) {
            breakpoint = 'navbar-expand';
          }
  
          return breakpoint;
        }
      },
      render: function render(h) {
        var _ref;
  
        return h(this.tag, {
          staticClass: 'navbar',
          class: [(_ref = {
            'd-print': this.print,
            'sticky-top': this.sticky
          }, _defineProperty(_ref, "navbar-".concat(this.type), this.type), _defineProperty(_ref, "bg-".concat(this.variant), this.variant), _defineProperty(_ref, "fixed-".concat(this.fixed), this.fixed), _ref), this.breakpointClass],
          attrs: {
            role: this.tag === 'nav' ? null : 'navigation'
          }
        }, [this.normalizeSlot('default')]);
      }
    });
  
    var props$O = pluckProps(['tag', 'fill', 'justified', 'align', 'small'], props$I); // -- Utils --
  
    var computeJustifyContent$1 = function computeJustifyContent(value) {
      // Normalize value
      value = value === 'left' ? 'start' : value === 'right' ? 'end' : value;
      return "justify-content-".concat(value);
    }; // @vue/component
  
  
    var BNavbarNav = /*#__PURE__*/Vue.extend({
      name: 'BNavbarNav',
      functional: true,
      props: props$O,
      render: function render(h, _ref) {
        var _class;
  
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        return h(props.tag, a(data, {
          staticClass: 'navbar-nav',
          class: (_class = {
            'nav-fill': props.fill,
            'nav-justified': props.justified
          }, _defineProperty(_class, computeJustifyContent$1(props.align), props.align), _defineProperty(_class, "small", props.small), _class)
        }), children);
      }
    });
  
    var linkProps$3 = propsFactory();
    linkProps$3.href.default = undefined;
    linkProps$3.to.default = undefined;
    var props$P = _objectSpread2({}, linkProps$3, {
      tag: {
        type: String,
        default: 'div'
      }
    }); // @vue/component
  
    var BNavbarBrand = /*#__PURE__*/Vue.extend({
      name: 'BNavbarBrand',
      functional: true,
      props: props$P,
      render: function render(h, _ref) {
        var props = _ref.props,
            data = _ref.data,
            children = _ref.children;
        var isLink = props.to || props.href;
        var tag = isLink ? BLink : props.tag;
        return h(tag, a(data, {
          staticClass: 'navbar-brand',
          props: isLink ? pluckProps(linkProps$3, props) : {}
        }), children);
      }
    });
  
    var NAME$r = 'BNavbarToggle'; // TODO: Switch to using VBToggle directive, will reduce code footprint
    // Events we emit on $root
  
    var EVENT_TOGGLE$2 = 'bv::toggle::collapse'; // Events we listen to on $root
  
    var EVENT_STATE$2 = 'bv::collapse::state'; // This private event is NOT to be documented as people should not be using it.
  
    var EVENT_STATE_SYNC$2 = 'bv::collapse::sync::state'; // @vue/component
  
    var BNavbarToggle = /*#__PURE__*/Vue.extend({
      name: NAME$r,
      mixins: [listenOnRootMixin, normalizeSlotMixin],
      props: {
        label: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$r, 'label');
          }
        },
        target: {
          type: String,
          required: true
        }
      },
      data: function data() {
        return {
          toggleState: false
        };
      },
      created: function created() {
        this.listenOnRoot(EVENT_STATE$2, this.handleStateEvt);
        this.listenOnRoot(EVENT_STATE_SYNC$2, this.handleStateEvt);
      },
      methods: {
        onClick: function onClick(evt) {
          this.$emit('click', evt);
  
          if (!evt.defaultPrevented) {
            this.$root.$emit(EVENT_TOGGLE$2, this.target);
          }
        },
        handleStateEvt: function handleStateEvt(id, state) {
          if (id === this.target) {
            this.toggleState = state;
          }
        }
      },
      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.normalizeSlot('default') || h('span', {
          class: ['navbar-toggler-icon']
        })]);
      }
    });
  
    var NavbarPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BNavbar: BNavbar,
        BNavbarNav: BNavbarNav,
        BNavbarBrand: BNavbarBrand,
        BNavbarToggle: BNavbarToggle,
        BNavToggle: BNavbarToggle
      },
      plugins: {
        NavPlugin: NavPlugin,
        CollapsePlugin: CollapsePlugin,
        DropdownPlugin: DropdownPlugin
      }
    });
  
    /**
     * @param {number} length
     * @return {Array}
     */
    var range = function range(length) {
      return Array.apply(null, {
        length: length
      });
    };
  
    // for `<b-pagination>` and `<b-pagination-nav>`
    // --- Constants ---
    // Threshold of limit size when we start/stop showing ellipsis
  
    var ELLIPSIS_THRESHOLD = 3; // Default # of buttons limit
  
    var DEFAULT_LIMIT = 5; // --- Helper methods ---
    // Make an array of N to N+X
  
    var makePageArray = function makePageArray(startNumber, numberOfPages) {
      return range(numberOfPages).map(function (val, i) {
        return {
          number: startNumber + i,
          classes: null
        };
      });
    }; // Sanitize the provided limit value (converting to a number)
  
  
    var sanitizeLimit = function sanitizeLimit(val) {
      var limit = toInteger(val) || 1;
      return limit < 1 ? DEFAULT_LIMIT : limit;
    }; // Sanitize the provided current page number (converting to a number)
  
  
    var sanitizeCurrentPage = function sanitizeCurrentPage(val, numberOfPages) {
      var page = toInteger(val) || 1;
      return page > numberOfPages ? numberOfPages : page < 1 ? 1 : page;
    }; // Links don't normally respond to SPACE, so we add that
    // functionality via this handler
  
  
    var onSpaceKey = function onSpaceKey(evt) {
      if (evt.keyCode === KEY_CODES.SPACE) {
        evt.preventDefault(); // Stop page from scrolling
  
        evt.stopImmediatePropagation();
        evt.stopPropagation(); // Trigger the click event on the link
  
        evt.currentTarget.click();
        return false;
      }
    }; // --- Props ---
  
  
    var props$Q = {
      disabled: {
        type: Boolean,
        default: false
      },
      value: {
        type: [Number, String],
        default: null,
        validator: function validator(value)
        /* istanbul ignore next */
        {
          var number = toInteger(value);
  
          if (!isNull(value) && (isNaN(number) || number < 1)) {
            warn('"v-model" value must be a number greater than "0"', 'BPagination');
            return false;
          }
  
          return true;
        }
      },
      limit: {
        type: [Number, String],
        default: DEFAULT_LIMIT,
        validator: function validator(value)
        /* istanbul ignore next */
        {
          var number = toInteger(value);
  
          if (isNaN(number) || number < 1) {
            warn('Prop "limit" must be a number greater than "0"', 'BPagination');
            return false;
          }
  
          return true;
        }
      },
      align: {
        type: String,
        default: 'left'
      },
      pills: {
        type: Boolean,
        default: false
      },
      hideGotoEndButtons: {
        type: Boolean,
        default: false
      },
      ariaLabel: {
        type: String,
        default: 'Pagination'
      },
      labelFirstPage: {
        type: String,
        default: 'Go to first page'
      },
      firstText: {
        type: String,
        default: "\xAB" // '«'
  
      },
      firstNumber: {
        type: Boolean,
        default: false
      },
      firstClass: {
        type: [String, Array, Object],
        default: null
      },
      labelPrevPage: {
        type: String,
        default: 'Go to previous page'
      },
      prevText: {
        type: String,
        default: "\u2039" // '‹'
  
      },
      prevClass: {
        type: [String, Array, Object],
        default: null
      },
      labelNextPage: {
        type: String,
        default: 'Go to next page'
      },
      nextText: {
        type: String,
        default: "\u203A" // '›'
  
      },
      nextClass: {
        type: [String, Array, Object],
        default: null
      },
      labelLastPage: {
        type: String,
        default: 'Go to last page'
      },
      lastText: {
        type: String,
        default: "\xBB" // '»'
  
      },
      lastNumber: {
        type: Boolean,
        default: false
      },
      lastClass: {
        type: [String, Array, Object],
        default: null
      },
      labelPage: {
        type: [String, Function],
        default: 'Go to page'
      },
      pageClass: {
        type: [String, Array, Object],
        default: null
      },
      hideEllipsis: {
        type: Boolean,
        default: false
      },
      ellipsisText: {
        type: String,
        default: "\u2026" // '…'
  
      },
      ellipsisClass: {
        type: [String, Array, Object],
        default: null
      }
    }; // @vue/component
  
    var paginationMixin = {
      mixins: [normalizeSlotMixin],
      model: {
        prop: 'value',
        event: 'input'
      },
      props: props$Q,
      data: function data() {
        var curr = toInteger(this.value);
        return {
          // -1 signifies no page initially selected
          currentPage: curr > 0 ? curr : -1,
          localNumberOfPages: 1,
          localLimit: DEFAULT_LIMIT
        };
      },
      computed: {
        btnSize: function btnSize() {
          return this.size ? "pagination-".concat(this.size) : '';
        },
        alignment: function alignment() {
          var align = this.align;
  
          if (align === 'center') {
            return 'justify-content-center';
          } else if (align === 'end' || align === 'right') {
            return 'justify-content-end';
          } else if (align === 'fill') {
            // The page-items will also have 'flex-fill' added
            // We add text centering to make the button appearance better in fill mode
            return 'text-center';
          }
  
          return '';
        },
        styleClass: function styleClass() {
          return this.pills ? 'b-pagination-pills' : '';
        },
        computedCurrentPage: function computedCurrentPage() {
          return sanitizeCurrentPage(this.currentPage, this.localNumberOfPages);
        },
        paginationParams: function paginationParams() {
          // Determine if we should show the the ellipsis
          var limit = this.localLimit;
          var numberOfPages = this.localNumberOfPages;
          var currentPage = this.computedCurrentPage;
          var hideEllipsis = this.hideEllipsis;
          var firstNumber = this.firstNumber;
          var lastNumber = this.lastNumber;
          var showFirstDots = false;
          var showLastDots = false;
          var numberOfLinks = limit;
          var startNumber = 1;
  
          if (numberOfPages <= limit) {
            // Special case: Less pages available than the limit of displayed pages
            numberOfLinks = numberOfPages;
          } else if (currentPage < limit - 1 && limit > ELLIPSIS_THRESHOLD) {
            if (!hideEllipsis || lastNumber) {
              showLastDots = true;
              numberOfLinks = limit - (firstNumber ? 0 : 1);
            }
  
            numberOfLinks = Math.min(numberOfLinks, limit);
          } else if (numberOfPages - currentPage + 2 < limit && limit > ELLIPSIS_THRESHOLD) {
            if (!hideEllipsis || firstNumber) {
              showFirstDots = true;
              numberOfLinks = limit - (lastNumber ? 0 : 1);
            }
  
            startNumber = numberOfPages - numberOfLinks + 1;
          } else {
            // We are somewhere in the middle of the page list
            if (limit > ELLIPSIS_THRESHOLD) {
              numberOfLinks = limit - 2;
              showFirstDots = !!(!hideEllipsis || firstNumber);
              showLastDots = !!(!hideEllipsis || lastNumber);
            }
  
            startNumber = currentPage - Math.floor(numberOfLinks / 2);
          } // Sanity checks
  
          /* istanbul ignore if */
  
  
          if (startNumber < 1) {
            startNumber = 1;
            showFirstDots = false;
          } else if (startNumber > numberOfPages - numberOfLinks) {
            startNumber = numberOfPages - numberOfLinks + 1;
            showLastDots = false;
          }
  
          if (showFirstDots && firstNumber && startNumber < 4) {
            numberOfLinks = numberOfLinks + 2;
            startNumber = 1;
            showFirstDots = false;
          }
  
          var lastPageNumber = startNumber + numberOfLinks - 1;
  
          if (showLastDots && lastNumber && lastPageNumber > numberOfPages - 3) {
            numberOfLinks = numberOfLinks + (lastPageNumber === numberOfPages - 2 ? 2 : 3);
            showLastDots = false;
          } // Special handling for lower limits (where ellipsis are never shown)
  
  
          if (limit <= ELLIPSIS_THRESHOLD) {
            if (firstNumber && startNumber === 1) {
              numberOfLinks = Math.min(numberOfLinks + 1, numberOfPages, limit + 1);
            } else if (lastNumber && numberOfPages === startNumber + numberOfLinks - 1) {
              startNumber = Math.max(startNumber - 1, 1);
              numberOfLinks = Math.min(numberOfPages - startNumber + 1, numberOfPages, limit + 1);
            }
          }
  
          numberOfLinks = Math.min(numberOfLinks, numberOfPages - startNumber + 1);
          return {
            showFirstDots: showFirstDots,
            showLastDots: showLastDots,
            numberOfLinks: numberOfLinks,
            startNumber: startNumber
          };
        },
        pageList: function pageList() {
          // Generates the pageList array
          var _this$paginationParam = this.paginationParams,
              numberOfLinks = _this$paginationParam.numberOfLinks,
              startNumber = _this$paginationParam.startNumber;
          var currentPage = this.computedCurrentPage; // Generate list of page numbers
  
          var pages = makePageArray(startNumber, numberOfLinks); // We limit to a total of 3 page buttons on XS screens
          // So add classes to page links to hide them for XS breakpoint
          // Note: Ellipsis will also be hidden on XS screens
          // TODO: Make this visual limit configurable based on breakpoint(s)
  
          if (pages.length > 3) {
            var idx = currentPage - startNumber; // THe following is a bootstrap-vue custom utility class
  
            var classes = 'bv-d-xs-down-none';
  
            if (idx === 0) {
              // Keep leftmost 3 buttons visible when current page is first page
              for (var i = 3; i < pages.length; i++) {
                pages[i].classes = classes;
              }
            } else if (idx === pages.length - 1) {
              // Keep rightmost 3 buttons visible when current page is last page
              for (var _i = 0; _i < pages.length - 3; _i++) {
                pages[_i].classes = classes;
              }
            } else {
              // Hide all except current page, current page - 1 and current page + 1
              for (var _i2 = 0; _i2 < idx - 1; _i2++) {
                // hide some left button(s)
                pages[_i2].classes = classes;
              }
  
              for (var _i3 = pages.length - 1; _i3 > idx + 1; _i3--) {
                // hide some right button(s)
                pages[_i3].classes = classes;
              }
            }
          }
  
          return pages;
        }
      },
      watch: {
        value: function value(newValue, oldValue) {
          if (newValue !== oldValue) {
            this.currentPage = sanitizeCurrentPage(newValue, this.localNumberOfPages);
          }
        },
        currentPage: function currentPage(newValue, oldValue) {
          if (newValue !== oldValue) {
            // Emit null if no page selected
            this.$emit('input', newValue > 0 ? newValue : null);
          }
        },
        limit: function limit(newValue, oldValue) {
          if (newValue !== oldValue) {
            this.localLimit = sanitizeLimit(newValue);
          }
        }
      },
      created: function created() {
        var _this = this;
  
        // Set our default values in data
        this.localLimit = sanitizeLimit(this.limit);
        this.$nextTick(function () {
          // Sanity check
          _this.currentPage = _this.currentPage > _this.localNumberOfPages ? _this.localNumberOfPages : _this.currentPage;
        });
      },
      methods: {
        handleKeyNav: function handleKeyNav(evt) {
          var keyCode = evt.keyCode,
              shiftKey = evt.shiftKey;
          /* istanbul ignore if */
  
          if (this.isNav) {
            // We disable left/right keyboard navigation in `<b-pagination-nav>`
            return;
          }
  
          if (keyCode === KEY_CODES.LEFT || keyCode === KEY_CODES.UP) {
            evt.preventDefault();
            shiftKey ? this.focusFirst() : this.focusPrev();
          } else if (keyCode === KEY_CODES.RIGHT || keyCode === KEY_CODES.DOWN) {
            evt.preventDefault();
            shiftKey ? this.focusLast() : this.focusNext();
          }
        },
        getButtons: function getButtons() {
          // Return only buttons that are visible
          return selectAll('button.page-link, a.page-link', this.$el).filter(function (btn) {
            return isVisible(btn);
          });
        },
        setBtnFocus: function setBtnFocus(btn) {
          btn.focus();
        },
        focusCurrent: function focusCurrent() {
          var _this2 = this;
  
          // We do this in `$nextTick()` to ensure buttons have finished rendering
          this.$nextTick(function () {
            var btn = _this2.getButtons().find(function (el) {
              return toInteger(getAttr(el, 'aria-posinset')) === _this2.computedCurrentPage;
            });
  
            if (btn && btn.focus) {
              _this2.setBtnFocus(btn);
            } else {
              // Fallback if current page is not in button list
              _this2.focusFirst();
            }
          });
        },
        focusFirst: function focusFirst() {
          var _this3 = this;
  
          // We do this in `$nextTick()` to ensure buttons have finished rendering
          this.$nextTick(function () {
            var btn = _this3.getButtons().find(function (el) {
              return !isDisabled(el);
            });
  
            if (btn && btn.focus && btn !== document.activeElement) {
              _this3.setBtnFocus(btn);
            }
          });
        },
        focusLast: function focusLast() {
          var _this4 = this;
  
          // We do this in `$nextTick()` to ensure buttons have finished rendering
          this.$nextTick(function () {
            var btn = _this4.getButtons().reverse().find(function (el) {
              return !isDisabled(el);
            });
  
            if (btn && btn.focus && btn !== document.activeElement) {
              _this4.setBtnFocus(btn);
            }
          });
        },
        focusPrev: function focusPrev() {
          var _this5 = this;
  
          // We do this in `$nextTick()` to ensure buttons have finished rendering
          this.$nextTick(function () {
            var buttons = _this5.getButtons();
  
            var idx = buttons.indexOf(document.activeElement);
  
            if (idx > 0 && !isDisabled(buttons[idx - 1]) && buttons[idx - 1].focus) {
              _this5.setBtnFocus(buttons[idx - 1]);
            }
          });
        },
        focusNext: function focusNext() {
          var _this6 = this;
  
          // We do this in `$nextTick()` to ensure buttons have finished rendering
          this.$nextTick(function () {
            var buttons = _this6.getButtons();
  
            var idx = buttons.indexOf(document.activeElement);
            var cnt = buttons.length - 1;
  
            if (idx < cnt && !isDisabled(buttons[idx + 1]) && buttons[idx + 1].focus) {
              _this6.setBtnFocus(buttons[idx + 1]);
            }
          });
        }
      },
      render: function render(h) {
        var _this7 = this;
  
        var buttons = [];
        var numberOfPages = this.localNumberOfPages;
        var pageNumbers = this.pageList.map(function (p) {
          return p.number;
        });
        var disabled = this.disabled;
        var _this$paginationParam2 = this.paginationParams,
            showFirstDots = _this$paginationParam2.showFirstDots,
            showLastDots = _this$paginationParam2.showLastDots;
        var currentPage = this.computedCurrentPage;
        var fill = this.align === 'fill'; // Used to control what type of aria attributes are rendered and wrapper
  
        var isNav = this.isNav; // Helper function and flag
  
        var isActivePage = function isActivePage(pageNumber) {
          return pageNumber === currentPage;
        };
  
        var noCurrentPage = this.currentPage < 1; // Factory function for prev/next/first/last buttons
  
        var makeEndBtn = function makeEndBtn(linkTo, ariaLabel, btnSlot, btnText, btnClass, pageTest, key) {
          var isDisabled = disabled || isActivePage(pageTest) || noCurrentPage || linkTo < 1 || linkTo > numberOfPages;
          var pageNumber = linkTo < 1 ? 1 : linkTo > numberOfPages ? numberOfPages : linkTo;
          var scope = {
            disabled: isDisabled,
            page: pageNumber,
            index: pageNumber - 1
          };
          var $btnContent = _this7.normalizeSlot(btnSlot, scope) || toString$1(btnText) || h();
          var $inner = h(isDisabled ? 'span' : isNav ? BLink : 'button', {
            staticClass: 'page-link',
            class: {
              'flex-grow-1': !isNav && !isDisabled && fill
            },
            props: isDisabled || !isNav ? {} : _this7.linkProps(linkTo),
            attrs: {
              role: isNav ? null : 'menuitem',
              type: isNav || isDisabled ? null : 'button',
              tabindex: isDisabled || isNav ? null : '-1',
              'aria-label': ariaLabel,
              'aria-controls': _this7.ariaControls || null,
              'aria-disabled': isDisabled ? 'true' : null
            },
            on: isDisabled ? {} : {
              '!click': function click(evt) {
                _this7.onClick(linkTo, evt);
              },
              keydown: onSpaceKey
            }
          }, [$btnContent]);
          return h('li', {
            key: key,
            staticClass: 'page-item',
            class: [{
              disabled: isDisabled,
              'flex-fill': fill,
              'd-flex': fill && !isNav && !isDisabled
            }, btnClass],
            attrs: {
              role: isNav ? null : 'presentation',
              'aria-hidden': isDisabled ? 'true' : null
            }
          }, [$inner]);
        }; // Ellipsis factory
  
  
        var makeEllipsis = function makeEllipsis(isLast) {
          return h('li', {
            key: "ellipsis-".concat(isLast ? 'last' : 'first'),
            staticClass: 'page-item',
            class: ['disabled', 'bv-d-xs-down-none', fill ? 'flex-fill' : '', _this7.ellipsisClass],
            attrs: {
              role: 'separator'
            }
          }, [h('span', {
            staticClass: 'page-link'
          }, [_this7.normalizeSlot('ellipsis-text') || toString$1(_this7.ellipsisText) || h()])]);
        }; // Page button factory
  
  
        var makePageButton = function makePageButton(page, idx) {
          var active = isActivePage(page.number) && !noCurrentPage; // Active page will have tabindex of 0, or if no current page and first page button
  
          var tabIndex = disabled ? null : active || noCurrentPage && idx === 0 ? '0' : '-1';
          var attrs = {
            role: isNav ? null : 'menuitemradio',
            type: isNav || disabled ? null : 'button',
            'aria-disabled': disabled ? 'true' : null,
            'aria-controls': _this7.ariaControls || null,
            'aria-label': isFunction(_this7.labelPage) ? _this7.labelPage(page.number) : "".concat(_this7.labelPage, " ").concat(page.number),
            'aria-checked': isNav ? null : active ? 'true' : 'false',
            'aria-current': isNav && active ? 'page' : null,
            'aria-posinset': page.number,
            'aria-setsize': numberOfPages,
            // ARIA "roving tabindex" method (except in isNav mode)
            tabindex: isNav ? null : tabIndex
          };
          var btnContent = toString$1(_this7.makePage(page.number));
          var scope = {
            page: page.number,
            index: page.number - 1,
            content: btnContent,
            active: active,
            disabled: disabled
          };
          var $inner = h(disabled ? 'span' : isNav ? BLink : 'button', {
            props: disabled || !isNav ? {} : _this7.linkProps(page.number),
            staticClass: 'page-link',
            class: {
              'flex-grow-1': !isNav && !disabled && fill
            },
            attrs: attrs,
            on: disabled ? {} : {
              '!click': function click(evt) {
                _this7.onClick(page.number, evt);
              },
              keydown: onSpaceKey
            }
          }, [_this7.normalizeSlot('page', scope) || btnContent]);
          return h('li', {
            key: "page-".concat(page.number),
            staticClass: 'page-item',
            class: [{
              disabled: disabled,
              active: active,
              'flex-fill': fill,
              'd-flex': fill && !isNav && !disabled
            }, page.classes, _this7.pageClass],
            attrs: {
              role: isNav ? null : 'presentation'
            }
          }, [$inner]);
        }; // Goto first page button
        // Don't render button when `hideGotoEndButtons` or `firstNumber` is set
  
  
        var $firstPageBtn = h();
  
        if (!this.firstNumber && !this.hideGotoEndButtons) {
          $firstPageBtn = makeEndBtn(1, this.labelFirstPage, 'first-text', this.firstText, this.firstClass, 1, 'pagination-goto-first');
        }
  
        buttons.push($firstPageBtn); // Goto previous page button
  
        buttons.push(makeEndBtn(currentPage - 1, this.labelPrevPage, 'prev-text', this.prevText, this.prevClass, 1, 'pagination-goto-prev')); // Show first (1) button?
  
        buttons.push(this.firstNumber && pageNumbers[0] !== 1 ? makePageButton({
          number: 1
        }, 0) : h()); // First ellipsis
  
        buttons.push(showFirstDots ? makeEllipsis(false) : h()); // Individual page links
  
        this.pageList.forEach(function (page, idx) {
          var offset = showFirstDots && _this7.firstNumber && pageNumbers[0] !== 1 ? 1 : 0;
          buttons.push(makePageButton(page, idx + offset));
        }); // Last ellipsis
  
        buttons.push(showLastDots ? makeEllipsis(true) : h()); // Show last page button?
  
        buttons.push(this.lastNumber && pageNumbers[pageNumbers.length - 1] !== numberOfPages ? makePageButton({
          number: numberOfPages
        }, -1) : h()); // Goto next page button
  
        buttons.push(makeEndBtn(currentPage + 1, this.labelNextPage, 'next-text', this.nextText, this.nextClass, numberOfPages, 'pagination-goto-next')); // Goto last page button
        // Don't render button when `hideGotoEndButtons` or `lastNumber` is set
  
        var $lastPageBtn = h();
  
        if (!this.lastNumber && !this.hideGotoEndButtons) {
          $lastPageBtn = makeEndBtn(numberOfPages, this.labelLastPage, 'last-text', this.lastText, this.lastClass, numberOfPages, 'pagination-goto-last');
        }
  
        buttons.push($lastPageBtn); // Assemble the pagination buttons
  
        var $pagination = h('ul', {
          ref: 'ul',
          staticClass: 'pagination',
          class: ['b-pagination', this.btnSize, this.alignment, this.styleClass],
          attrs: {
            role: isNav ? null : 'menubar',
            'aria-disabled': disabled ? 'true' : 'false',
            'aria-label': isNav ? null : this.ariaLabel || null
          },
          // We disable keyboard left/right nav when `<b-pagination-nav>`
          on: isNav ? {} : {
            keydown: this.handleKeyNav
          }
        }, buttons); // If we are `<b-pagination-nav>`, wrap in `<nav>` wrapper
  
        if (isNav) {
          return h('nav', {
            attrs: {
              'aria-disabled': disabled ? 'true' : null,
              'aria-hidden': disabled ? 'true' : 'false',
              'aria-label': isNav ? this.ariaLabel || null : null
            }
          }, [$pagination]);
        }
  
        return $pagination;
      }
    };
  
    var NAME$s = 'BPagination';
    var DEFAULT_PER_PAGE = 20;
    var DEFAULT_TOTAL_ROWS = 0;
    var props$R = {
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$s, 'size');
        }
      },
      perPage: {
        type: [Number, String],
        default: DEFAULT_PER_PAGE
      },
      totalRows: {
        type: [Number, String],
        default: DEFAULT_TOTAL_ROWS
      },
      ariaControls: {
        type: String,
        default: null
      }
    }; // --- Helper functions ---
    // Sanitize the provided per page number (converting to a number)
  
    var sanitizePerPage = function sanitizePerPage(val) {
      var perPage = toInteger(val) || DEFAULT_PER_PAGE;
      return perPage < 1 ? 1 : perPage;
    }; // Sanitize the provided total rows number (converting to a number)
  
  
    var sanitizeTotalRows = function sanitizeTotalRows(val) {
      var totalRows = toInteger(val) || DEFAULT_TOTAL_ROWS;
      return totalRows < 0 ? 0 : totalRows;
    }; // The render function is brought in via the `paginationMixin`
    // @vue/component
  
  
    var BPagination = /*#__PURE__*/Vue.extend({
      name: NAME$s,
      mixins: [paginationMixin],
      props: props$R,
      computed: {
        numberOfPages: function numberOfPages() {
          var result = Math.ceil(sanitizeTotalRows(this.totalRows) / sanitizePerPage(this.perPage));
          return result < 1 ? 1 : result;
        },
        pageSizeNumberOfPages: function pageSizeNumberOfPages() {
          // Used for watching changes to `perPage` and `numberOfPages`
          return {
            perPage: sanitizePerPage(this.perPage),
            totalRows: sanitizeTotalRows(this.totalRows),
            numberOfPages: this.numberOfPages
          };
        }
      },
      watch: {
        pageSizeNumberOfPages: function pageSizeNumberOfPages(newVal, oldVal) {
          if (!isUndefinedOrNull(oldVal)) {
            if (newVal.perPage !== oldVal.perPage && newVal.totalRows === oldVal.totalRows) {
              // If the page size changes, reset to page 1
              this.currentPage = 1;
            } else if (newVal.numberOfPages !== oldVal.numberOfPages && this.currentPage > newVal.numberOfPages) {
              // If `numberOfPages` changes and is less than
              // the `currentPage` number, reset to page 1
              this.currentPage = 1;
            }
          }
  
          this.localNumberOfPages = newVal.numberOfPages;
        }
      },
      created: function created() {
        var _this = this;
  
        // Set the initial page count
        this.localNumberOfPages = this.numberOfPages; // Set the initial page value
  
        var currentPage = toInteger(this.value) || 0;
  
        if (currentPage > 0) {
          this.currentPage = currentPage;
        } else {
          this.$nextTick(function () {
            // If this value parses to NaN or a value less than 1
            // Trigger an initial emit of 'null' if no page specified
            _this.currentPage = 0;
          });
        }
      },
      mounted: function mounted() {
        // Set the initial page count
        this.localNumberOfPages = this.numberOfPages;
      },
      methods: {
        // These methods are used by the render function
        onClick: function onClick(num, evt) {
          var _this2 = this;
  
          // Handle edge cases where number of pages has changed (i.e. if perPage changes)
          // This should normally not happen, but just in case.
          if (num > this.numberOfPages) {
            /* istanbul ignore next */
            num = this.numberOfPages;
          } else if (num < 1) {
            /* istanbul ignore next */
            num = 1;
          } // Update the v-model
  
  
          this.currentPage = num; // Emit event triggered by user interaction
  
          this.$emit('change', this.currentPage);
          this.$nextTick(function () {
            // Keep the current button focused if possible
            var target = evt.target;
  
            if (isVisible(target) && _this2.$el.contains(target) && target.focus) {
              target.focus();
            } else {
              _this2.focusCurrent();
            }
          });
        },
        makePage: function makePage(pageNum) {
          return pageNum;
        },
        linkProps: function linkProps() {
          // No props, since we render a plain button
  
          /* istanbul ignore next */
          return {};
        }
      }
    });
  
    var PaginationPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BPagination: BPagination
      }
    });
  
    var NAME$t = 'BPaginationNav'; // Sanitize the provided number of pages (converting to a number)
  
    var sanitizeNumberOfPages = function sanitizeNumberOfPages(value) {
      var numberOfPages = toInteger(value) || 1;
      return numberOfPages < 1 ? 1 : numberOfPages;
    };
    var props$S = {
      size: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$t, 'size');
        }
      },
      numberOfPages: {
        type: [Number, String],
        default: 1,
        validator: function validator(value)
        /* istanbul ignore next */
        {
          var num = toInteger(value);
  
          if (isNaN(num) || num < 1) {
            warn('Prop "number-of-pages" must be a number greater than "0"', NAME$t);
            return false;
          }
  
          return true;
        }
      },
      baseUrl: {
        type: String,
        default: '/'
      },
      useRouter: {
        type: Boolean,
        default: false
      },
      linkGen: {
        type: Function,
        default: null
      },
      pageGen: {
        type: Function,
        default: null
      },
      pages: {
        // Optional array of page links
        type: Array,
        default: null
      },
      noPageDetect: {
        // Disable auto page number detection if true
        type: Boolean,
        default: false
      },
      // router-link specific props
      activeClass: {
        type: String // default: undefined
  
      },
      exact: {
        type: Boolean,
        default: false
      },
      exactActiveClass: {
        type: String // default: undefined
  
      },
      // nuxt-link specific prop(s)
      noPrefetch: {
        type: Boolean,
        default: false
      }
    }; // The render function is brought in via the pagination mixin
    // @vue/component
  
    var BPaginationNav = /*#__PURE__*/Vue.extend({
      name: NAME$t,
      mixins: [paginationMixin],
      props: props$S,
      computed: {
        // Used by render function to trigger wrapping in '<nav>' element
        isNav: function isNav() {
          return true;
        },
        computedValue: function computedValue() {
          // Returns the value prop as a number or `null` if undefined or < 1
          var val = toInteger(this.value);
          return isNaN(val) || val < 1 ? null : val;
        }
      },
      watch: {
        numberOfPages: function numberOfPages() {
          var _this = this;
  
          this.$nextTick(function () {
            _this.setNumberOfPages();
          });
        },
        pages: function pages() {
          var _this2 = this;
  
          this.$nextTick(function () {
            _this2.setNumberOfPages();
          });
        }
      },
      created: function created() {
        this.setNumberOfPages();
      },
      mounted: function mounted() {
        var _this3 = this;
  
        if (this.$router) {
          // We only add the watcher if vue router is detected
          this.$watch('$route', function () {
            _this3.$nextTick(function () {
              requestAF(function () {
                _this3.guessCurrentPage();
              });
            });
          });
        }
      },
      methods: {
        setNumberOfPages: function setNumberOfPages() {
          var _this4 = this;
  
          if (isArray(this.pages) && this.pages.length > 0) {
            this.localNumberOfPages = this.pages.length;
          } else {
            this.localNumberOfPages = sanitizeNumberOfPages(this.numberOfPages);
          }
  
          this.$nextTick(function () {
            _this4.guessCurrentPage();
          });
        },
        onClick: function onClick(pageNum, evt) {
          var _this5 = this;
  
          // Dont do anything if clicking the current active page
          if (pageNum === this.currentPage) {
            return;
          }
  
          requestAF(function () {
            // Update the v-model
            // Done in in requestAF() to allow browser to complete the
            // native browser click handling of a link
            _this5.currentPage = pageNum;
  
            _this5.$emit('change', pageNum);
          });
          this.$nextTick(function () {
            // Done in a nextTick() to ensure rendering complete
            try {
              // Emulate native link click page reloading behaviour by blurring the
              // paginator and returning focus to the document
              var target = evt.currentTarget || evt.target;
              target.blur();
            } catch (e) {}
          });
        },
        getPageInfo: function getPageInfo(pageNum) {
          if (!isArray(this.pages) || this.pages.length === 0 || isUndefined(this.pages[pageNum - 1])) {
            var link = "".concat(this.baseUrl).concat(pageNum);
            return {
              link: this.useRouter ? {
                path: link
              } : link,
              text: toString$1(pageNum)
            };
          }
  
          var info = this.pages[pageNum - 1];
  
          if (isObject(info)) {
            var _link = info.link;
            return {
              // Normalize link for router use
              link: isObject(_link) ? _link : this.useRouter ? {
                path: _link
              } : _link,
              // Make sure text has a value
              text: toString$1(info.text || pageNum)
            };
          } else {
            return {
              link: toString$1(info),
              text: toString$1(pageNum)
            };
          }
        },
        makePage: function makePage(pageNum) {
          var info = this.getPageInfo(pageNum);
  
          if (this.pageGen && isFunction(this.pageGen)) {
            return this.pageGen(pageNum, info);
          }
  
          return info.text;
        },
        makeLink: function makeLink(pageNum) {
          var info = this.getPageInfo(pageNum);
  
          if (this.linkGen && isFunction(this.linkGen)) {
            return this.linkGen(pageNum, info);
          }
  
          return info.link;
        },
        linkProps: function linkProps(pageNum) {
          var link = this.makeLink(pageNum);
          var props = {
            target: this.target || null,
            rel: this.rel || null,
            disabled: this.disabled,
            // The following props are only used if BLink detects router
            exact: this.exact,
            activeClass: this.activeClass,
            exactActiveClass: this.exactActiveClass,
            append: this.append,
            replace: this.replace,
            // nuxt-link specific prop
            noPrefetch: this.noPrefetch
          };
  
          if (this.useRouter || isObject(link)) {
            props.to = link;
          } else {
            props.href = link;
          }
  
          return props;
        },
        resolveLink: function resolveLink() {
          var to = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
          // Given a to (or href string), convert to normalized route-like structure
          // Works only client side!!
          var link;
  
          try {
            // Convert the `to` to a HREF via a temporary `a` tag
            link = document.createElement('a');
            link.href = computeHref({
              to: to
            }, 'a', '/', '/'); // We need to add the anchor to the document to make sure the
            // `pathname` is correctly detected in any browser (i.e. IE)
  
            document.body.appendChild(link); // Once href is assigned, the link will be normalized to the full URL bits
  
            var _link2 = link,
                pathname = _link2.pathname,
                hash = _link2.hash,
                search = _link2.search; // Remove link from document
  
            document.body.removeChild(link); // Return the location in a route-like object
  
            return {
              path: pathname,
              hash: hash,
              query: parseQuery(search)
            };
          } catch (e) {
            /* istanbul ignore next */
            try {
              link && link.parentNode && link.parentNode.removeChild(link);
            } catch (e) {}
            /* istanbul ignore next */
  
  
            return {};
          }
        },
        resolveRoute: function resolveRoute() {
          var to = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  
          // Given a to (or href string), convert to normalized route location structure
          // works only when router available!!
          try {
            var route = this.$router.resolve(to, this.$route).route;
            return {
              path: route.path,
              hash: route.hash,
              query: route.query
            };
          } catch (e) {
            /* istanbul ignore next */
            return {};
          }
        },
        guessCurrentPage: function guessCurrentPage() {
          var guess = this.computedValue;
          var $router = this.$router;
          var $route = this.$route; // This section only occurs if we are client side, or server-side with $router
  
          /* istanbul ignore else */
  
          if (!this.noPageDetect && !guess && (isBrowser || !isBrowser && $router)) {
            // Current route (if router available)
            var currRoute = $router && $route ? {
              path: $route.path,
              hash: $route.hash,
              query: $route.query
            } : {}; // Current page full HREF (if client side). Can't be done as a computed prop!
  
            var loc = isBrowser ? window.location || document.location : null;
            var currLink = loc ? {
              path: loc.pathname,
              hash: loc.hash,
              query: parseQuery(loc.search)
            } : {}; // Loop through the possible pages looking for a match until found
  
            for (var page = 1; !guess && page <= this.localNumberOfPages; page++) {
              var to = this.makeLink(page);
  
              if ($router && (isObject(to) || this.useRouter)) {
                // Resolve the page via the $router
                guess = looseEqual(this.resolveRoute(to), currRoute) ? page : null;
              } else if (isBrowser) {
                // If no $router available (or !this.useRouter when `to` is a string)
                // we compare using parsed URIs
                guess = looseEqual(this.resolveLink(to), currLink) ? page : null;
              } else {
                // probably SSR, but no $router so we can't guess, so lets break out of
                // the loop early
  
                /* istanbul ignore next */
                guess = -1;
              }
            }
          } // We set currentPage to 0 to trigger an $emit('input', null)
          // As the default for this.currentPage is -1 when no value is specified
          // And valid page numbers are greater than 0
  
  
          this.currentPage = guess > 0 ? guess : 0;
        }
      }
    });
  
    var PaginationNavPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BPaginationNav: BPaginationNav
      }
    });
  
    // Base on-demand component for tooltip / popover templates
    var NAME$u = 'BVPopper';
    var AttachmentMap$1 = {
      AUTO: 'auto',
      TOP: 'top',
      RIGHT: 'right',
      BOTTOM: 'bottom',
      LEFT: 'left',
      TOPLEFT: 'top',
      TOPRIGHT: 'top',
      RIGHTTOP: 'right',
      RIGHTBOTTOM: 'right',
      BOTTOMLEFT: 'bottom',
      BOTTOMRIGHT: 'bottom',
      LEFTTOP: 'left',
      LEFTBOTTOM: 'left'
    };
    var OffsetMap = {
      AUTO: 0,
      TOPLEFT: -1,
      TOP: 0,
      TOPRIGHT: +1,
      RIGHTTOP: -1,
      RIGHT: 0,
      RIGHTBOTTOM: +1,
      BOTTOMLEFT: -1,
      BOTTOM: 0,
      BOTTOMRIGHT: +1,
      LEFTTOP: -1,
      LEFT: 0,
      LEFTBOTTOM: +1
    }; // @vue/component
  
    var BVPopper = /*#__PURE__*/Vue.extend({
      name: NAME$u,
      props: {
        target: {
          // Element that the tooltip/popover is positioned relative to
          type: [HTMLElement, SVGElement],
          default: null
        },
        placement: {
          type: String,
          default: 'top'
        },
        fallbackPlacement: {
          type: [String, Array],
          default: 'flip'
        },
        offset: {
          type: Number,
          default: 0
        },
        boundary: {
          // 'scrollParent', 'viewport', 'window', or Element
          type: [String, HTMLElement],
          default: 'scrollParent'
        },
        boundaryPadding: {
          // Tooltip/popover will try and stay away from
          // boundary edge by this many pixels
          type: Number,
          default: 5
        },
        arrowPadding: {
          // The minimum distance (in `px`) from the edge of the
          // tooltip/popover that the arrow can be positioned
          type: Number,
          default: 6
        }
      },
      data: function data() {
        return {
          // reactive props set by parent
          noFade: false,
          // State related data
          localShow: true,
          attachment: this.getAttachment(this.placement)
        };
      },
      computed: {
        templateType: function templateType()
        /* istanbul ignore next */
        {
          // Overridden by template component
          return 'unknown';
        },
        popperConfig: function popperConfig() {
          var _this = this;
  
          var placement = this.placement;
          return {
            placement: this.getAttachment(placement),
            modifiers: {
              offset: {
                offset: this.getOffset(placement)
              },
              flip: {
                behavior: this.fallbackPlacement
              },
              // `arrow.element` can also be a reference to an HTML Element
              // maybe we should make this a `$ref` in the templates?
              arrow: {
                element: '.arrow'
              },
              preventOverflow: {
                padding: this.boundaryPadding,
                boundariesElement: this.boundary
              }
            },
            onCreate: function onCreate(data) {
              // Handle flipping arrow classes
              if (data.originalPlacement !== data.placement) {
                /* istanbul ignore next: can't test in JSDOM */
                _this.popperPlacementChange(data);
              }
            },
            onUpdate: function onUpdate(data) {
              // Handle flipping arrow classes
              _this.popperPlacementChange(data);
            }
          };
        }
      },
      created: function created() {
        var _this2 = this;
  
        // Note: We are created on-demand, and should be guaranteed that
        // DOM is rendered/ready by the time the created hook runs
        this.$_popper = null; // Ensure we show as we mount
  
        this.localShow = true; // Create popper instance before shown
  
        this.$on('show', function (el) {
          _this2.popperCreate(el);
        }); // Self destruct once hidden
  
        this.$on('hidden', function () {
          _this2.$nextTick(_this2.$destroy);
        }); // If parent is destroyed, ensure we are destroyed
  
        this.$parent.$once('hook:destroyed', this.$destroy);
      },
      beforeMount: function beforeMount() {
        // Ensure that the attachment position is correct before mounting
        // as our propsData is added after `new Template({...})`
        this.attachment = this.getAttachment(this.placement);
      },
      mounted: function mounted() {// TBD
      },
      updated: function updated() {
        // Update popper if needed
        // TODO: Should this be a watcher on `this.popperConfig` instead?
        this.popperUpdate();
      },
      beforeDestroy: function beforeDestroy() {
        this.popperDestroy();
      },
      destroyed: function destroyed() {
        // Make sure template is removed from DOM
        var el = this.$el;
        el && el.parentNode && el.parentNode.removeChild(el);
      },
      methods: {
        // "Public" method to trigger hide template
        hide: function hide() {
          this.localShow = false;
        },
        // Private
        getAttachment: function getAttachment(placement) {
          return AttachmentMap$1[String(placement).toUpperCase()] || 'auto';
        },
        getOffset: function getOffset(placement) {
          if (!this.offset) {
            // Could set a ref for the arrow element
            var arrow = this.$refs.arrow || select('.arrow', this.$el);
            var arrowOffset = (parseFloat(getCS(arrow).width) || 0) + (parseFloat(this.arrowPadding) || 0);
  
            switch (OffsetMap[String(placement).toUpperCase()] || 0) {
              case +1:
                /* istanbul ignore next: can't test in JSDOM */
                return "+50%p - ".concat(arrowOffset, "px");
  
              case -1:
                /* istanbul ignore next: can't test in JSDOM */
                return "-50%p + ".concat(arrowOffset, "px");
  
              default:
                return 0;
            }
          }
          /* istanbul ignore next */
  
  
          return this.offset;
        },
        popperCreate: function popperCreate(el) {
          this.popperDestroy(); // We use `el` rather than `this.$el` just in case the original
          // mountpoint root element type was changed by the template
  
          this.$_popper = new Popper(this.target, el, this.popperConfig);
        },
        popperDestroy: function popperDestroy() {
          this.$_popper && this.$_popper.destroy();
          this.$_popper = null;
        },
        popperUpdate: function popperUpdate() {
          this.$_popper && this.$_popper.scheduleUpdate();
        },
        popperPlacementChange: function popperPlacementChange(data) {
          // Callback used by popper to adjust the arrow placement
          this.attachment = this.getAttachment(data.placement);
        },
        renderTemplate: function renderTemplate(h)
        /* istanbul ignore next */
        {
          // Will be overridden by templates
          return h('div');
        }
      },
      render: function render(h) {
        var _this3 = this;
  
        // Note: `show` and 'fade' classes are only appled during transition
        return h(BVTransition, {
          // Transitions as soon as mounted
          props: {
            appear: true,
            noFade: this.noFade
          },
          on: {
            // Events used by parent component/instance
            beforeEnter: function beforeEnter(el) {
              return _this3.$emit('show', el);
            },
            afterEnter: function afterEnter(el) {
              return _this3.$emit('shown', el);
            },
            beforeLeave: function beforeLeave(el) {
              return _this3.$emit('hide', el);
            },
            afterLeave: function afterLeave(el) {
              return _this3.$emit('hidden', el);
            }
          }
        }, [this.localShow ? this.renderTemplate(h) : h()]);
      }
    });
  
    var NAME$v = 'BVTooltipTemplate'; // @vue/component
  
    var BVTooltipTemplate = /*#__PURE__*/Vue.extend({
      name: NAME$v,
      extends: BVPopper,
      mixins: [scopedStyleAttrsMixin],
      props: {
        // Other non-reactive (while open) props are pulled in from BVPopper
        id: {
          type: String,
          default: null
        },
        html: {
          // Used only by the directive versions
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        // We use data, rather than props to ensure reactivity
        // Parent component will directly set this data
        return {
          title: '',
          content: '',
          variant: null,
          customClass: null,
          interactive: true
        };
      },
      computed: {
        templateType: function templateType() {
          return 'tooltip';
        },
        templateClasses: function templateClasses() {
          var _ref;
  
          return [(_ref = {
            // Disables pointer events to hide the tooltip when the user
            // hovers over its content
            noninteractive: !this.interactive
          }, _defineProperty(_ref, "b-".concat(this.templateType, "-").concat(this.variant), this.variant), _defineProperty(_ref, "bs-".concat(this.templateType, "-").concat(this.attachment), this.attachment), _ref), this.customClass];
        },
        templateAttributes: function templateAttributes() {
          return _objectSpread2({
            id: this.id,
            role: 'tooltip',
            tabindex: '-1'
          }, this.scopedStyleAttrs);
        },
        templateListeners: function templateListeners() {
          var _this = this;
  
          // Used for hover/focus trigger listeners
          return {
            mouseenter: function mouseenter(evt) {
              /* istanbul ignore next: difficult to test in JSDOM */
              _this.$emit('mouseenter', evt);
            },
            mouseleave: function mouseleave(evt) {
              /* istanbul ignore next: difficult to test in JSDOM */
              _this.$emit('mouseleave', evt);
            },
            focusin: function focusin(evt) {
              /* istanbul ignore next: difficult to test in JSDOM */
              _this.$emit('focusin', evt);
            },
            focusout: function focusout(evt) {
              /* istanbul ignore next: difficult to test in JSDOM */
              _this.$emit('focusout', evt);
            }
          };
        }
      },
      methods: {
        renderTemplate: function renderTemplate(h) {
          // Title can be a scoped slot function
          var $title = isFunction(this.title) ? this.title({}) : isUndefinedOrNull(this.title) ? h() : this.title; // Directive versions only
  
          var domProps = this.html && !isFunction(this.title) ? {
            innerHTML: this.title
          } : {};
          return h('div', {
            staticClass: 'tooltip b-tooltip',
            class: this.templateClasses,
            attrs: this.templateAttributes,
            on: this.templateListeners
          }, [h('div', {
            ref: 'arrow',
            staticClass: 'arrow'
          }), h('div', {
            staticClass: 'tooltip-inner',
            domProps: domProps
          }, [$title])]);
        }
      }
    });
  
    var NAME$w = 'BVTooltip'; // Modal container selector for appending tooltip/popover
  
    var MODAL_SELECTOR = '.modal-content'; // Modal `$root` hidden event
  
    var MODAL_CLOSE_EVENT = 'bv::modal::hidden'; // For dropdown sniffing
  
    var DROPDOWN_CLASS = 'dropdown';
    var DROPDOWN_OPEN_SELECTOR = '.dropdown-menu.show'; // Data specific to popper and template
    // We don't use props, as we need reactivity (we can't pass reactive props)
  
    var templateData = {
      // Text string or Scoped slot function
      title: '',
      // Text string or Scoped slot function
      content: '',
      // String
      variant: null,
      // String, Array, Object
      customClass: null,
      // String or array of Strings (overwritten by BVPopper)
      triggers: '',
      // String (overwritten by BVPopper)
      placement: 'auto',
      // String or array of strings
      fallbackPlacement: 'flip',
      // Element or Component reference (or function that returns element) of
      // the element that will have the trigger events bound, and is also
      // default element for positioning
      target: null,
      // HTML ID, Element or Component reference
      container: null,
      // 'body'
      // Boolean
      noFade: false,
      // 'scrollParent', 'viewport', 'window', Element, or Component reference
      boundary: 'scrollParent',
      // Tooltip/popover will try and stay away from
      // boundary edge by this many pixels (Number)
      boundaryPadding: 5,
      // Arrow offset (Number)
      offset: 0,
      // Hover/focus delay (Number or Object)
      delay: 0,
      // Arrow of Tooltip/popover will try and stay away from
      // the edge of tooltip/popover edge by this many pixels
      arrowPadding: 6,
      // Interactive state (Boolean)
      interactive: true,
      // Disabled state (Boolean)
      disabled: false,
      // ID to use for tooltip/popover
      id: null,
      // Flag used by directives only, for HTML content
      html: false
    }; // @vue/component
  
    var BVTooltip = /*#__PURE__*/Vue.extend({
      name: NAME$w,
      props: {// None
      },
      data: function data() {
        return _objectSpread2({}, templateData, {
          // State management data
          activeTrigger: {
            // manual: false,
            hover: false,
            click: false,
            focus: false
          },
          localShow: false
        });
      },
      computed: {
        templateType: function templateType() {
          // Overwritten by BVPopover
          return 'tooltip';
        },
        computedId: function computedId() {
          return this.id || "__bv_".concat(this.templateType, "_").concat(this._uid, "__");
        },
        computedDelay: function computedDelay() {
          // Normalizes delay into object form
          var delay = {
            show: 0,
            hide: 0
          };
  
          if (isPlainObject(this.delay)) {
            delay.show = Math.max(parseInt(this.delay.show, 10) || 0, 0);
            delay.hide = Math.max(parseInt(this.delay.hide, 10) || 0, 0);
          } else if (isNumber(this.delay) || isString(this.delay)) {
            delay.show = delay.hide = Math.max(parseInt(this.delay, 10) || 0, 0);
          }
  
          return delay;
        },
        computedTriggers: function computedTriggers() {
          // Returns the triggers in sorted array form
          // TODO: Switch this to object form for easier lookup
          return concat(this.triggers).filter(Boolean).join(' ').trim().toLowerCase().split(/\s+/).sort();
        },
        isWithActiveTrigger: function isWithActiveTrigger() {
          for (var trigger in this.activeTrigger) {
            if (this.activeTrigger[trigger]) {
              return true;
            }
          }
  
          return false;
        },
        computedTemplateData: function computedTemplateData() {
          return {
            title: this.title,
            content: this.content,
            variant: this.variant,
            customClass: this.customClass,
            noFade: this.noFade,
            interactive: this.interactive
          };
        }
      },
      watch: {
        computedTriggers: function computedTriggers(newTriggers, oldTriggers) {
          var _this = this;
  
          // Triggers have changed, so re-register them
  
          /* istanbul ignore next */
          if (!looseEqual(newTriggers, oldTriggers)) {
            this.$nextTick(function () {
              // Disable trigger listeners
              _this.unListen(); // Clear any active triggers that are no longer in the list of triggers
  
  
              oldTriggers.forEach(function (trigger) {
                if (!arrayIncludes(newTriggers, trigger)) {
                  if (_this.activeTrigger[trigger]) {
                    _this.activeTrigger[trigger] = false;
                  }
                }
              }); // Re-enable the trigger listeners
  
              _this.listen();
            });
          }
        },
        computedTemplateData: function computedTemplateData() {
          // If any of the while open reactive "props" change,
          // ensure that the template updates accordingly
          this.handleTemplateUpdate();
        },
        disabled: function disabled(newVal) {
          newVal ? this.disable() : this.enable();
        }
      },
      created: function created() {
        var _this2 = this;
  
        // Create non-reactive properties
        this.$_tip = null;
        this.$_hoverTimeout = null;
        this.$_hoverState = '';
        this.$_visibleInterval = null;
        this.$_enabled = !this.disabled;
        this.$_noop = noop.bind(this); // Destroy ourselves when the parent is destroyed
  
        if (this.$parent) {
          this.$parent.$once('hook:beforeDestroy', this.$destroy);
        }
  
        this.$nextTick(function () {
          var target = _this2.getTarget();
  
          if (target && contains(document.body, target)) {
            // Copy the parent's scoped style attribute
            _this2.scopeId = getScopeId(_this2.$parent); // Set up all trigger handlers and listeners
  
            _this2.listen();
          } else {
            /* istanbul ignore next */
            warn('Unable to find target element in document.', _this2.templateType);
          }
        });
      },
      updated: function updated()
      /* istanbul ignore next */
      {
        // Usually called when the slots/data changes
        this.$nextTick(this.handleTemplateUpdate);
      },
      deactivated: function deactivated()
      /* istanbul ignore next */
      {
        // In a keepalive that has been deactivated, so hide
        // the tooltip/popover if it is showing
        this.forceHide();
      },
      beforeDestroy: function beforeDestroy()
      /* istanbul ignore next */
      {
        // Remove all handler/listeners
        this.unListen();
        this.setWhileOpenListeners(false); // Clear any timeouts/intervals
  
        this.clearHoverTimeout();
        this.clearVisibilityInterval(); // Destroy the template
  
        this.destroyTemplate();
      },
      methods: {
        // --- Methods for creating and destroying the template ---
        getTemplate: function getTemplate() {
          // Overridden by BVPopover
          return BVTooltipTemplate;
        },
        updateData: function updateData() {
          var _this3 = this;
  
          var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
          // Method for updating popper/template data
          // We only update data if it exists, and has not changed
          var titleUpdated = false;
          keys(templateData).forEach(function (prop) {
            if (!isUndefined(data[prop]) && _this3[prop] !== data[prop]) {
              _this3[prop] = data[prop];
  
              if (prop === 'title') {
                titleUpdated = true;
              }
            }
          });
  
          if (titleUpdated && this.localShow) {
            // If the title has updated, we may need to handle the title
            // attribute on the trigger target. We only do this while the
            // template is open
            this.fixTitle();
          }
        },
        createTemplateAndShow: function createTemplateAndShow() {
          // Creates the template instance and show it
          var container = this.getContainer();
          var Template = this.getTemplate();
          var $tip = this.$_tip = new Template({
            parent: this,
            // The following is not reactive to changes in the props data
            propsData: {
              // These values cannot be changed while template is showing
              id: this.computedId,
              html: this.html,
              placement: this.placement,
              fallbackPlacement: this.fallbackPlacement,
              target: this.getPlacementTarget(),
              boundary: this.getBoundary(),
              // Ensure the following are integers
              offset: parseInt(this.offset, 10) || 0,
              arrowPadding: parseInt(this.arrowPadding, 10) || 0,
              boundaryPadding: parseInt(this.boundaryPadding, 10) || 0
            }
          }); // We set the initial reactive data (values that can be changed while open)
  
          this.handleTemplateUpdate(); // Template transition phase events (handled once only)
          // When the template has mounted, but not visibly shown yet
  
          $tip.$once('show', this.onTemplateShow); // When the template has completed showing
  
          $tip.$once('shown', this.onTemplateShown); // When the template has started to hide
  
          $tip.$once('hide', this.onTemplateHide); // When the template has completed hiding
  
          $tip.$once('hidden', this.onTemplateHidden); // When the template gets destroyed for any reason
  
          $tip.$once('hook:destroyed', this.destroyTemplate); // Convenience events from template
          // To save us from manually adding/removing DOM
          // listeners to tip element when it is open
  
          $tip.$on('focusin', this.handleEvent);
          $tip.$on('focusout', this.handleEvent);
          $tip.$on('mouseenter', this.handleEvent);
          $tip.$on('mouseleave', this.handleEvent); // Mount (which triggers the `show`)
  
          $tip.$mount(container.appendChild(document.createElement('div'))); // Template will automatically remove its markup from DOM when hidden
        },
        hideTemplate: function hideTemplate() {
          // Trigger the template to start hiding
          // The template will emit the `hide` event after this and
          // then emit the `hidden` event once it is fully hidden
          // The `hook:destroyed` will also be called (safety measure)
          this.$_tip && this.$_tip.hide(); // Clear out any stragging active triggers
  
          this.clearActiveTriggers(); // Reset the hover state
  
          this.$_hoverState = '';
        },
        // Destroy the template instance and reset state
        destroyTemplate: function destroyTemplate() {
          this.setWhileOpenListeners(false);
          this.clearHoverTimeout();
          this.$_hoverState = '';
          this.clearActiveTriggers();
          this.localPlacementTarget = null;
  
          try {
            this.$_tip && this.$_tip.$destroy();
          } catch (_unused) {}
  
          this.$_tip = null;
          this.removeAriaDescribedby();
          this.restoreTitle();
          this.localShow = false;
        },
        getTemplateElement: function getTemplateElement() {
          return this.$_tip ? this.$_tip.$el : null;
        },
        handleTemplateUpdate: function handleTemplateUpdate() {
          var _this4 = this;
  
          // Update our template title/content "props"
          // So that the template updates accordingly
          var $tip = this.$_tip;
  
          if ($tip) {
            var props = ['title', 'content', 'variant', 'customClass', 'noFade', 'interactive']; // Only update the values if they have changed
  
            props.forEach(function (prop) {
              if ($tip[prop] !== _this4[prop]) {
                $tip[prop] = _this4[prop];
              }
            });
          }
        },
        // --- Show/Hide handlers ---
        // Show the tooltip
        show: function show() {
          var target = this.getTarget();
  
          if (!target || !contains(document.body, target) || !isVisible(target) || this.dropdownOpen() || (isUndefinedOrNull(this.title) || this.title === '') && (isUndefinedOrNull(this.content) || this.content === '')) {
            // If trigger element isn't in the DOM or is not visible, or
            // is on an open dropdown toggle, or has no content, then
            // we exit without showing
            return;
          } // If tip already exists, exit early
  
  
          if (this.$_tip || this.localShow) {
            /* istanbul ignore next */
            return;
          } // In the process of showing
  
  
          this.localShow = true; // Create a cancelable BvEvent
  
          var showEvt = this.buildEvent('show', {
            cancelable: true
          });
          this.emitEvent(showEvt); // Don't show if event cancelled
  
          /* istanbul ignore next: ignore for now */
  
          if (showEvt.defaultPrevented) {
            // Destroy the template (if for some reason it was created)
  
            /* istanbul ignore next */
            this.destroyTemplate();
            /* istanbul ignore next */
  
            return;
          } // Fix the title attribute on target
  
  
          this.fixTitle(); // Set aria-describedby on target
  
          this.addAriaDescribedby(); // Create and show the tooltip
  
          this.createTemplateAndShow();
        },
        hide: function hide() {
          var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
          // Hide the tooltip
          var tip = this.getTemplateElement();
  
          if (!tip || !this.localShow) {
            /* istanbul ignore next */
            this.restoreTitle();
            /* istanbul ignore next */
  
            return;
          } // Emit cancelable BvEvent 'hide'
          // We disable cancelling if `force` is true
  
  
          var hideEvt = this.buildEvent('hide', {
            cancelable: !force
          });
          this.emitEvent(hideEvt);
          /* istanbul ignore next: ignore for now */
  
          if (hideEvt.defaultPrevented) {
            // Don't hide if event cancelled
  
            /* istanbul ignore next */
            return;
          } // Tell the template to hide
  
  
          this.hideTemplate();
        },
        forceHide: function forceHide() {
          // Forcefully hides/destroys the template, regardless of any active triggers
          var tip = this.getTemplateElement();
  
          if (!tip || !this.localShow) {
            /* istanbul ignore next */
            return;
          } // Disable while open listeners/watchers
          // This is also done in the template `hide` evt handler
  
  
          this.setWhileOpenListeners(false); // Clear any hover enter/leave event
  
          this.clearHoverTimeout();
          this.$_hoverState = '';
          this.clearActiveTriggers(); // Disable the fade animation on the template
  
          if (this.$_tip) {
            this.$_tip.noFade = true;
          } // Hide the tip (with force = true)
  
  
          this.hide(true);
        },
        enable: function enable() {
          this.$_enabled = true; // Create a non-cancelable BvEvent
  
          this.emitEvent(this.buildEvent('enabled'));
        },
        disable: function disable() {
          this.$_enabled = false; // Create a non-cancelable BvEvent
  
          this.emitEvent(this.buildEvent('disabled'));
        },
        // --- Handlers for template events ---
        // When template is inserted into DOM, but not yet shown
        onTemplateShow: function onTemplateShow() {
          // Enable while open listeners/watchers
          this.setWhileOpenListeners(true);
        },
        // When template show transition completes
        onTemplateShown: function onTemplateShown() {
          var prevHoverState = this.$_hoverState;
          this.$_hoverState = '';
  
          if (prevHoverState === 'out') {
            this.leave(null);
          } // Emit a non-cancelable BvEvent 'shown'
  
  
          this.emitEvent(this.buildEvent('shown'));
        },
        // When template is starting to hide
        onTemplateHide: function onTemplateHide() {
          // Disable while open listeners/watchers
          this.setWhileOpenListeners(false);
        },
        // When template has completed closing (just before it self destructs)
        onTemplateHidden: function onTemplateHidden() {
          // Destroy the template
          this.destroyTemplate(); // Emit a non-cancelable BvEvent 'shown'
  
          this.emitEvent(this.buildEvent('hidden'));
        },
        // --- Utility methods ---
        getTarget: function getTarget() {
          // Handle case where target may be a component ref
          var target = this.target ? this.target.$el || this.target : null; // If an ID
  
          target = isString(target) ? getById(target.replace(/^#/, '')) : target; // If a function
  
          target = isFunction(target) ? target() : target; // If an element ref
  
          return isElement(target) ? target : null;
        },
        getPlacementTarget: function getPlacementTarget() {
          // This is the target that the tooltip will be placed on, which may not
          // necessarily be the same element that has the trigger event listeners
          // For now, this is the same as target
          // TODO:
          //   Add in child selector support
          //   Add in visibility checks for this element
          //   Fallback to target if not found
          return this.getTarget();
        },
        getTargetId: function getTargetId() {
          // Returns the ID of the trigger element
          var target = this.getTarget();
          return target && target.id ? target.id : null;
        },
        getContainer: function getContainer() {
          // Handle case where container may be a component ref
          var container = this.container ? this.container.$el || this.container : false;
          var body = document.body;
          var target = this.getTarget(); // If we are in a modal, we append to the modal instead
          // of body, unless a container is specified
          // TODO:
          //   Template should periodically check to see if it is in dom
          //   And if not, self destruct (if container got v-if'ed out of DOM)
          //   Or this could possibly be part of the visibility check
  
          return container === false ? closest(MODAL_SELECTOR, target) || body : isString(container) ? getById(container.replace(/^#/, '')) || body : body;
        },
        getBoundary: function getBoundary() {
          return this.boundary ? this.boundary.$el || this.boundary : 'scrollParent';
        },
        isInModal: function isInModal() {
          var target = this.getTarget();
          return target && closest(MODAL_SELECTOR, target);
        },
        isDropdown: function isDropdown() {
          // Returns true if trigger is a dropdown
          var target = this.getTarget();
          return target && hasClass(target, DROPDOWN_CLASS);
        },
        dropdownOpen: function dropdownOpen() {
          // Returns true if trigger is a dropdown and the dropdown menu is open
          var target = this.getTarget();
          return this.isDropdown() && target && select(DROPDOWN_OPEN_SELECTOR, target);
        },
        clearHoverTimeout: function clearHoverTimeout() {
          if (this.$_hoverTimeout) {
            clearTimeout(this.$_hoverTimeout);
            this.$_hoverTimeout = null;
          }
        },
        clearVisibilityInterval: function clearVisibilityInterval() {
          if (this.$_visibleInterval) {
            clearInterval(this.$_visibleInterval);
            this.$_visibleInterval = null;
          }
        },
        clearActiveTriggers: function clearActiveTriggers() {
          for (var trigger in this.activeTrigger) {
            this.activeTrigger[trigger] = false;
          }
        },
        addAriaDescribedby: function addAriaDescribedby() {
          // Add aria-describedby on trigger element, without removing any other IDs
          var target = this.getTarget();
          var desc = getAttr(target, 'aria-describedby') || '';
          desc = desc.split(/\s+/).concat(this.computedId).join(' ').trim(); // Update/add aria-described by
  
          setAttr(target, 'aria-describedby', desc);
        },
        removeAriaDescribedby: function removeAriaDescribedby() {
          var _this5 = this;
  
          // Remove aria-describedby on trigger element, without removing any other IDs
          var target = this.getTarget();
          var desc = getAttr(target, 'aria-describedby') || '';
          desc = desc.split(/\s+/).filter(function (d) {
            return d !== _this5.computedId;
          }).join(' ').trim(); // Update or remove aria-describedby
  
          if (desc) {
            /* istanbul ignore next */
            setAttr(target, 'aria-describedby', desc);
          } else {
            removeAttr(target, 'aria-describedby');
          }
        },
        fixTitle: function fixTitle() {
          // If the target has a title attribute, null it out and
          // store on data-title
          var target = this.getTarget();
  
          if (target && getAttr(target, 'title')) {
            // We only update title attribute if it has a value
            setAttr(target, 'data-original-title', getAttr(target, 'title') || '');
            setAttr(target, 'title', '');
          }
        },
        restoreTitle: function restoreTitle() {
          // If target had a title, restore the title attribute
          // and remove the data-title attribute
          var target = this.getTarget();
  
          if (target && hasAttr(target, 'data-original-title')) {
            setAttr(target, 'title', getAttr(target, 'data-original-title') || '');
            removeAttr(target, 'data-original-title');
          }
        },
        // --- BvEvent helpers ---
        buildEvent: function buildEvent(type) {
          var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
          // Defaults to a non-cancellable event
          return new BvEvent(type, _objectSpread2({
            cancelable: false,
            target: this.getTarget(),
            relatedTarget: this.getTemplateElement() || null,
            componentId: this.computedId,
            vueTarget: this
          }, options));
        },
        emitEvent: function emitEvent(bvEvt) {
          // Emits a BvEvent on $root and this instance
          var evtName = bvEvt.type;
          var $root = this.$root;
  
          if ($root && $root.$emit) {
            // Emit an event on $root
            $root.$emit("bv::".concat(this.templateType, "::").concat(evtName), bvEvt);
          }
  
          this.$emit(evtName, bvEvt);
        },
        // --- Event handler setup methods ---
        listen: function listen() {
          var _this6 = this;
  
          // Enable trigger event handlers
          var el = this.getTarget();
  
          if (!el) {
            /* istanbul ignore next */
            return;
          } // Listen for global show/hide events
  
  
          this.setRootListener(true); // Set up our listeners on the target trigger element
  
          this.computedTriggers.forEach(function (trigger) {
            if (trigger === 'click') {
              eventOn(el, 'click', _this6.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
            } else if (trigger === 'focus') {
              eventOn(el, 'focusin', _this6.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
              eventOn(el, 'focusout', _this6.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
            } else if (trigger === 'blur') {
              // Used to close $tip when element looses focus
  
              /* istanbul ignore next */
              eventOn(el, 'focusout', _this6.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
            } else if (trigger === 'hover') {
              eventOn(el, 'mouseenter', _this6.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
              eventOn(el, 'mouseleave', _this6.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
            }
          }, this);
        },
        unListen: function unListen()
        /* istanbul ignore next */
        {
          var _this7 = this;
  
          // Remove trigger event handlers
          var events = ['click', 'focusin', 'focusout', 'mouseenter', 'mouseleave'];
          var target = this.getTarget(); // Stop listening for global show/hide/enable/disable events
  
          this.setRootListener(false); // Clear out any active target listeners
  
          events.forEach(function (evt) {
            target && eventOff(target, evt, _this7.handleEvent, EVENT_OPTIONS_NO_CAPTURE);
          }, this);
        },
        setRootListener: function setRootListener(on) {
          // Listen for global `bv::{hide|show}::{tooltip|popover}` hide request event
          var $root = this.$root;
  
          if ($root) {
            var method = on ? '$on' : '$off';
            var type = this.templateType;
            $root[method]("bv::hide::".concat(type), this.doHide);
            $root[method]("bv::show::".concat(type), this.doShow);
            $root[method]("bv::disable::".concat(type), this.doDisable);
            $root[method]("bv::enable::".concat(type), this.doEnable);
          }
        },
        setWhileOpenListeners: function setWhileOpenListeners(on) {
          // Events that are only registered when the template is showing
          // Modal close events
          this.setModalListener(on); // Dropdown open events (if we are attached to a dropdown)
  
          this.setDropdownListener(on); // Periodic $element visibility check
          // For handling when tip target is in <keepalive>, tabs, carousel, etc
  
          this.visibleCheck(on); // On-touch start listeners
  
          this.setOnTouchStartListener(on);
        },
        // Handler for periodic visibility check
        visibleCheck: function visibleCheck(on) {
          var _this8 = this;
  
          this.clearVisibilityInterval();
          var target = this.getTarget();
          var tip = this.getTemplateElement();
  
          if (on) {
            this.$_visibleInterval = setInterval(function () {
              if (tip && _this8.localShow && (!target.parentNode || !isVisible(target))) {
                // Target element is no longer visible or not in DOM, so force-hide the tooltip
                _this8.forceHide();
              }
            }, 100);
          }
        },
        setModalListener: function setModalListener(on) {
          // Handle case where tooltip/target is in a modal
          if (this.isInModal()) {
            // We can listen for modal hidden events on `$root`
            this.$root[on ? '$on' : '$off'](MODAL_CLOSE_EVENT, this.forceHide);
          }
        },
        setOnTouchStartListener: function setOnTouchStartListener(on)
        /* istanbul ignore next: JSDOM doesn't support `ontouchstart` */
        {
          var _this9 = 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) {
            from(document.body.children).forEach(function (el) {
              eventOnOff(on, el, 'mouseover', _this9.$_noop);
            });
          }
        },
        setDropdownListener: function setDropdownListener(on) {
          var target = this.getTarget();
  
          if (!target || !this.$root || !this.isDropdown) {
            return;
          } // We can listen for dropdown shown events on its instance
          // TODO:
          //   We could grab the ID from the dropdown, and listen for
          //   $root events for that particular dropdown id
          //   Dropdown shown and hidden events will need to emit
          //   Note: Dropdown auto-ID happens in a `$nextTick()` after mount
          //         So the ID lookup would need to be done in a `$nextTick()`
  
  
          if (target.__vue__) {
            target.__vue__[on ? '$on' : '$off']('shown', this.forceHide);
          }
        },
        // --- Event handlers ---
        handleEvent: function handleEvent(evt) {
          // General trigger event handler
          // target is the trigger element
          var target = this.getTarget();
  
          if (!target || isDisabled(target) || !this.$_enabled || this.dropdownOpen()) {
            // If disabled or not enabled, or if a dropdown that is open, don't do anything
            // If tip is shown before element gets disabled, then tip will not
            // close until no longer disabled or forcefully closed
            return;
          }
  
          var type = evt.type;
          var triggers = this.computedTriggers;
  
          if (type === 'click' && arrayIncludes(triggers, 'click')) {
            this.click(evt);
          } else if (type === 'mouseenter' && arrayIncludes(triggers, 'hover')) {
            // `mouseenter` is a non-bubbling event
            this.enter(evt);
          } else if (type === 'focusin' && arrayIncludes(triggers, 'focus')) {
            // `focusin` is a bubbling event
            // `evt` includes `relatedTarget` (element loosing focus)
            this.enter(evt);
          } else if (type === 'focusout' && (arrayIncludes(triggers, 'focus') || arrayIncludes(triggers, 'blur')) || type === 'mouseleave' && arrayIncludes(triggers, 'hover')) {
            // `focusout` is a bubbling event
            // `mouseleave` is a non-bubbling event
            // `tip` is the template (will be null if not open)
            var tip = this.getTemplateElement(); // `evtTarget` is the element which is loosing focus/hover and
  
            var evtTarget = evt.target; // `relatedTarget` is the element gaining focus/hover
  
            var relatedTarget = evt.relatedTarget;
            /* istanbul ignore next */
  
            if ( // From tip to target
            tip && contains(tip, evtTarget) && contains(target, relatedTarget) || // From target to tip
            tip && contains(target, evtTarget) && contains(tip, relatedTarget) || // Within tip
            tip && contains(tip, evtTarget) && contains(tip, relatedTarget) || // Within target
            contains(target, evtTarget) && contains(target, relatedTarget)) {
              // If focus/hover moves within `tip` and `target`, don't trigger a leave
              return;
            } // Otherwise trigger a leave
  
  
            this.leave(evt);
          }
        },
        doHide: function doHide(id) {
          // Programmatically hide tooltip or popover
          if (!id || this.getTargetId() === id || this.computedId === id) {
            // Close all tooltips or popovers, or this specific tip (with ID)
            this.forceHide();
          }
        },
        doShow: function doShow(id) {
          // Programmatically show tooltip or popover
          if (!id || this.getTargetId() === id || this.computedId === id) {
            // Open all tooltips or popovers, or this specific tip (with ID)
            this.show();
          }
        },
        doDisable: function doDisable(id)
        /*istanbul ignore next: ignore for now */
        {
          // Programmatically disable tooltip or popover
          if (!id || this.getTargetId() === id || this.computedId === id) {
            // Disable all tooltips or popovers (no ID), or this specific tip (with ID)
            this.disable();
          }
        },
        doEnable: function doEnable(id)
        /*istanbul ignore next: ignore for now */
        {
          // Programmatically enable tooltip or popover
          if (!id || this.getTargetId() === id || this.computedId === id) {
            // Enable all tooltips or popovers (no ID), or this specific tip (with ID)
            this.enable();
          }
        },
        click: function click() {
          if (!this.$_enabled || this.dropdownOpen()) {
            /* istanbul ignore next */
            return;
          }
  
          this.activeTrigger.click = !this.activeTrigger.click;
  
          if (this.isWithActiveTrigger) {
            this.enter(null);
          } else {
            /* istanbul ignore next */
            this.leave(null);
          }
        },
        toggle: function toggle()
        /* istanbul ignore next */
        {
          // Manual toggle handler
          if (!this.$_enabled || this.dropdownOpen()) {
            /* istanbul ignore next */
            return;
          } // Should we register as an active trigger?
          // this.activeTrigger.manual = !this.activeTrigger.manual
  
  
          if (this.localShow) {
            this.leave(null);
          } else {
            this.enter(null);
          }
        },
        enter: function enter() {
          var _this10 = this;
  
          var evt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
  
          // Opening trigger handler
          // Note: Click events are sent with evt === null
          if (evt) {
            this.activeTrigger[evt.type === 'focusin' ? 'focus' : 'hover'] = true;
          }
          /* istanbul ignore next */
  
  
          if (this.localShow || this.$_hoverState === 'in') {
            this.$_hoverState = 'in';
            return;
          }
  
          this.clearHoverTimeout();
          this.$_hoverState = 'in';
  
          if (!this.computedDelay.show) {
            this.show();
          } else {
            // Hide any title attribute while enter delay is active
            this.fixTitle();
            this.$_hoverTimeout = setTimeout(function () {
              /* istanbul ignore else */
              if (_this10.$_hoverState === 'in') {
                _this10.show();
              } else if (!_this10.localShow) {
                _this10.restoreTitle();
              }
            }, this.computedDelay.show);
          }
        },
        leave: function leave() {
          var _this11 = this;
  
          var evt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
  
          // Closing trigger handler
          // Note: Click events are sent with evt === null
          if (evt) {
            this.activeTrigger[evt.type === 'focusout' ? 'focus' : 'hover'] = false;
            /* istanbul ignore next */
  
            if (evt.type === 'focusout' && arrayIncludes(this.computedTriggers, 'blur')) {
              // Special case for `blur`: we clear out the other triggers
              this.activeTrigger.click = false;
              this.activeTrigger.hover = false;
            }
          }
          /* istanbul ignore next: ignore for now */
  
  
          if (this.isWithActiveTrigger) {
            return;
          }
  
          this.clearHoverTimeout();
          this.$_hoverState = 'out';
  
          if (!this.computedDelay.hide) {
            this.hide();
          } else {
            this.$_hoverTimeout = setTimeout(function () {
              if (_this11.$_hoverState === 'out') {
                _this11.hide();
              }
            }, this.computedDelay.hide);
          }
        }
      }
    });
  
    var NAME$x = 'BTooltip'; // @vue/component
  
    var BTooltip = /*#__PURE__*/Vue.extend({
      name: NAME$x,
      props: {
        title: {
          type: String // default: undefined
  
        },
        // Added in by BPopover
        // content: {
        //   type: String,
        //   default: undefined
        // },
        target: {
          // String ID of element, or element/component reference
          // Or function that returns one of the above
          type: [String, HTMLElement, SVGElement, Function, Object],
          // default: undefined,
          required: true
        },
        triggers: {
          type: [String, Array],
          default: 'hover focus'
        },
        placement: {
          type: String,
          default: 'top'
        },
        fallbackPlacement: {
          type: [String, Array],
          default: 'flip',
          validator: function validator(value) {
            return isArray(value) && value.every(function (v) {
              return isString(v);
            }) || arrayIncludes(['flip', 'clockwise', 'counterclockwise'], value);
          }
        },
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$x, 'variant');
          }
        },
        customClass: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$x, 'customClass');
          }
        },
        delay: {
          type: [Number, Object, String],
          default: function _default() {
            return getComponentConfig(NAME$x, 'delay');
          }
        },
        boundary: {
          // String: scrollParent, window, or viewport
          // Element: element reference
          // Object: Vue component
          type: [String, HTMLElement, Object],
          default: function _default() {
            return getComponentConfig(NAME$x, 'boundary');
          }
        },
        boundaryPadding: {
          type: [Number, String],
          default: function _default() {
            return getComponentConfig(NAME$x, 'boundaryPadding');
          }
        },
        offset: {
          type: [Number, String],
          default: 0
        },
        noFade: {
          type: Boolean,
          default: false
        },
        container: {
          // String: HTML ID of container, if null body is used (default)
          // HTMLElement: element reference reference
          // Object: Vue Component
          type: [String, HTMLElement, Object] // default: undefined
  
        },
        show: {
          type: Boolean,
          default: false
        },
        noninteractive: {
          type: Boolean,
          default: false
        },
        disabled: {
          type: Boolean,
          default: false
        },
        id: {
          // ID to use for tooltip element
          // If not provided on will automatically be generated
          type: String,
          default: null
        }
      },
      data: function data() {
        return {
          localShow: this.show,
          localTitle: '',
          localContent: ''
        };
      },
      computed: {
        templateData: function templateData() {
          // Data that will be passed to the template and popper
          return {
            // We use massaged versions of the title and content props/slots
            title: this.localTitle,
            content: this.localContent,
            // Pass these props as is
            target: this.target,
            triggers: this.triggers,
            placement: this.placement,
            fallbackPlacement: this.fallbackPlacement,
            variant: this.variant,
            customClass: this.customClass,
            container: this.container,
            boundary: this.boundary,
            boundaryPadding: this.boundaryPadding,
            delay: this.delay,
            offset: this.offset,
            noFade: this.noFade,
            interactive: !this.noninteractive,
            disabled: this.disabled,
            id: this.id
          };
        },
        templateTitleContent: function templateTitleContent() {
          // Used to watch for changes to the title and content props
          return {
            title: this.title,
            content: this.content
          };
        }
      },
      watch: {
        show: function show(_show, oldVal) {
          if (_show !== oldVal && _show !== this.localShow && this.$_bv_toolpop) {
            if (_show) {
              this.$_bv_toolpop.show();
            } else {
              // We use `forceHide()` to override any active triggers
              this.$_bv_toolpop.forceHide();
            }
          }
        },
        disabled: function disabled(newVal) {
          if (newVal) {
            this.doDisable();
          } else {
            this.doEnable();
          }
        },
        localShow: function localShow(newVal) {
          // TODO: May need to be done in a `$nextTick()`
          this.$emit('update:show', newVal);
        },
        templateData: function templateData() {
          var _this = this;
  
          this.$nextTick(function () {
            if (_this.$_bv_toolpop) {
              _this.$_bv_toolpop.updateData(_this.templateData);
            }
          });
        },
        // Watchers for title/content props (prop changes do not trigger the `updated()` hook)
        templateTitleContent: function templateTitleContent() {
          this.$nextTick(this.updateContent);
        }
      },
      created: function created() {
        // Non reactive properties
        this.$_bv_toolpop = null;
      },
      updated: function updated() {
        // Update the `propData` object
        // Done in a `$nextTick()` to ensure slot(s) have updated
        this.$nextTick(this.updateContent);
      },
      beforeDestroy: function beforeDestroy() {
        // Shutdown our local event listeners
        this.$off('open', this.doOpen);
        this.$off('close', this.doClose);
        this.$off('disable', this.doDisable);
        this.$off('enable', this.doEnable); // Destroy the tip instance
  
        this.$_bv_toolpop && this.$_bv_toolpop.$destroy();
        this.$_bv_toolpop = null;
      },
      mounted: function mounted() {
        var _this2 = this;
  
        // Instantiate a new BVTooltip instance
        // Done in a `$nextTick()` to ensure DOM has completed rendering
        // so that target can be found
        this.$nextTick(function () {
          // Load the on demand child instance
          var Component = _this2.getComponent(); // Ensure we have initial content
  
  
          _this2.updateContent(); // Pass down the scoped style attribute if available
  
  
          var scopeId = getScopeId(_this2) || getScopeId(_this2.$parent); // Create the instance
  
          var $toolpop = _this2.$_bv_toolpop = new Component({
            parent: _this2,
            // Pass down the scoped style ID
            _scopeId: scopeId || undefined
          }); // Set the initial data
  
          $toolpop.updateData(_this2.templateData); // Set listeners
  
          $toolpop.$on('show', _this2.onShow);
          $toolpop.$on('shown', _this2.onShown);
          $toolpop.$on('hide', _this2.onHide);
          $toolpop.$on('hidden', _this2.onHidden);
          $toolpop.$on('disabled', _this2.onDisabled);
          $toolpop.$on('enabled', _this2.onEnabled); // Initially disabled?
  
          if (_this2.disabled) {
            // Initially disabled
            _this2.doDisable();
          } // Listen to open signals from others
  
  
          _this2.$on('open', _this2.doOpen); // Listen to close signals from others
  
  
          _this2.$on('close', _this2.doClose); // Listen to disable signals from others
  
  
          _this2.$on('disable', _this2.doDisable); // Listen to enable signals from others
  
  
          _this2.$on('enable', _this2.doEnable); // Initially show tooltip?
  
  
          if (_this2.localShow) {
            _this2.$_bv_toolpop && _this2.$_bv_toolpop.show();
          }
        });
      },
      methods: {
        getComponent: function getComponent() {
          // Overridden by BPopover
          return BVTooltip;
        },
        updateContent: function updateContent() {
          // Overridden by BPopover
          // Tooltip: Default slot is `title`
          // Popover: Default slot is `content`, `title` slot is title
          // We pass a scoped slot function reference by default (Vue v2.6x)
          // And pass the title prop as a fallback
          this.setTitle(this.$scopedSlots.default || this.title);
        },
        // Helper methods for `updateContent()`
        setTitle: function setTitle(val) {
          val = isUndefinedOrNull(val) ? '' : val; // We only update the value if it has changed
  
          if (this.localTitle !== val) {
            this.localTitle = val;
          }
        },
        setContent: function setContent(val) {
          val = isUndefinedOrNull(val) ? '' : val; // We only update the value if it has changed
  
          if (this.localContent !== val) {
            this.localContent = val;
          }
        },
        // --- Template event handlers ---
        onShow: function onShow(bvEvt) {
          // Placeholder
          this.$emit('show', bvEvt);
  
          if (bvEvt) {
            this.localShow = !bvEvt.defaultPrevented;
          }
        },
        onShown: function onShown(bvEvt) {
          // Tip is now showing
          this.localShow = true;
          this.$emit('shown', bvEvt);
        },
        onHide: function onHide(bvEvt) {
          this.$emit('hide', bvEvt);
        },
        onHidden: function onHidden(bvEvt) {
          // Tip is no longer showing
          this.$emit('hidden', bvEvt);
          this.localShow = false;
        },
        onDisabled: function onDisabled(bvEvt) {
          // Prevent possible endless loop if user mistakenly
          // fires `disabled` instead of `disable`
          if (bvEvt && bvEvt.type === 'disabled') {
            this.$emit('update:disabled', true);
            this.$emit('disabled', bvEvt);
          }
        },
        onEnabled: function onEnabled(bvEvt) {
          // Prevent possible endless loop if user mistakenly
          // fires `enabled` instead of `enable`
          if (bvEvt && bvEvt.type === 'enabled') {
            this.$emit('update:disabled', false);
            this.$emit('enabled', bvEvt);
          }
        },
        // --- Local event listeners ---
        doOpen: function doOpen() {
          !this.localShow && this.$_bv_toolpop && this.$_bv_toolpop.show();
        },
        doClose: function doClose() {
          this.localShow && this.$_bv_toolpop && this.$_bv_toolpop.hide();
        },
        doDisable: function doDisable() {
          this.$_bv_toolpop && this.$_bv_toolpop.disable();
        },
        doEnable: function doEnable() {
          this.$_bv_toolpop && this.$_bv_toolpop.enable();
        }
      },
      render: function render(h) {
        // Always renders a comment node
        // TODO:
        //   Future: Possibly render a target slot (single root element)
        //   which we can apply the listeners to (pass `this.$el` to BVTooltip)
        return h();
      }
    });
  
    var NAME$y = 'BVPopoverTemplate'; // @vue/component
  
    var BVPopoverTemplate = /*#__PURE__*/Vue.extend({
      name: NAME$y,
      extends: BVTooltipTemplate,
      computed: {
        templateType: function templateType() {
          return 'popover';
        }
      },
      methods: {
        renderTemplate: function renderTemplate(h) {
          // Title and content could be a scoped slot function
          var $title = isFunction(this.title) ? this.title({}) : this.title;
          var $content = isFunction(this.content) ? this.content({}) : this.content; // Directive usage only
  
          var titleDomProps = this.html && !isFunction(this.title) ? {
            innerHTML: this.title
          } : {};
          var contentDomProps = this.html && !isFunction(this.content) ? {
            innerHTML: this.content
          } : {};
          return h('div', {
            staticClass: 'popover b-popover',
            class: this.templateClasses,
            attrs: this.templateAttributes,
            on: this.templateListeners
          }, [h('div', {
            ref: 'arrow',
            staticClass: 'arrow'
          }), isUndefinedOrNull($title) || $title === '' ? h() : h('h3', {
            staticClass: 'popover-header',
            domProps: titleDomProps
          }, [$title]), isUndefinedOrNull($content) || $content === '' ? h() : h('div', {
            staticClass: 'popover-body',
            domProps: contentDomProps
          }, [$content])]);
        }
      }
    });
  
    // Popover "Class" (Built as a renderless Vue instance)
    var NAME$z = 'BVPopover'; // @vue/component
  
    var BVPopover = /*#__PURE__*/Vue.extend({
      name: NAME$z,
      extends: BVTooltip,
      computed: {
        // Overwrites BVTooltip
        templateType: function templateType() {
          return 'popover';
        }
      },
      methods: {
        getTemplate: function getTemplate() {
          // Overwrites BVTooltip
          return BVPopoverTemplate;
        }
      }
    });
  
    var NAME$A = 'BPopover';
    var BPopover = /*#__PURE__*/Vue.extend({
      name: NAME$A,
      extends: BTooltip,
      inheritAttrs: false,
      props: {
        title: {
          type: String // default: undefined
  
        },
        content: {
          type: String // default: undefined
  
        },
        triggers: {
          type: [String, Array],
          default: 'click'
        },
        placement: {
          type: String,
          default: 'right'
        },
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$A, 'variant');
          }
        },
        customClass: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$A, 'customClass');
          }
        },
        delay: {
          type: [Number, Object, String],
          default: function _default() {
            return getComponentConfig(NAME$A, 'delay');
          }
        },
        boundary: {
          // String: scrollParent, window, or viewport
          // Element: element reference
          // Object: Vue component
          type: [String, HTMLElement, Object],
          default: function _default() {
            return getComponentConfig(NAME$A, 'boundary');
          }
        },
        boundaryPadding: {
          type: [Number, String],
          default: function _default() {
            return getComponentConfig(NAME$A, 'boundaryPadding');
          }
        }
      },
      methods: {
        getComponent: function getComponent() {
          // Overridden by BPopover
          return BVPopover;
        },
        updateContent: function updateContent() {
          // Tooltip: Default slot is `title`
          // Popover: Default slot is `content`, `title` slot is title
          // We pass a scoped slot function references by default (Vue v2.6x)
          // And pass the title prop as a fallback
          this.setContent(this.$scopedSlots.default || this.content);
          this.setTitle(this.$scopedSlots.title || this.title);
        }
      } // Render function provided by BTooltip
  
    });
  
    var BV_POPOVER = '__BV_Popover__'; // Default trigger
  
    var DefaultTrigger = 'click'; // Valid event triggers
  
    var validTriggers = {
      focus: true,
      hover: true,
      click: true,
      blur: true,
      manual: true
    }; // Directive modifier test regular expressions. Pre-compile for performance
  
    var htmlRE = /^html$/i;
    var noFadeRE = /^nofade$/i;
    var placementRE = /^(auto|top(left|right)?|bottom(left|right)?|left(top|bottom)?|right(top|bottom)?)$/i;
    var boundaryRE = /^(window|viewport|scrollParent)$/i;
    var delayRE = /^d\d+$/i;
    var delayShowRE = /^ds\d+$/i;
    var delayHideRE = /^dh\d+$/i;
    var offsetRE = /^o-?\d+$/i;
    var variantRE = /^v-.+$/i;
    var spacesRE = /\s+/; // Build a Popover config based on bindings (if any)
    // Arguments and modifiers take precedence over passed value config object
  
    var parseBindings = function parseBindings(bindings, vnode)
    /* istanbul ignore next: not easy to test */
    {
      // We start out with a basic config
      var NAME = 'BPopover';
      var config = {
        title: undefined,
        content: undefined,
        trigger: '',
        // Default set below if needed
        placement: 'right',
        fallbackPlacement: 'flip',
        container: false,
        // Default of body
        animation: true,
        offset: 0,
        disabled: false,
        id: null,
        html: false,
        delay: getComponentConfig(NAME, 'delay'),
        boundary: String(getComponentConfig(NAME, 'boundary')),
        boundaryPadding: parseInt(getComponentConfig(NAME, 'boundaryPadding'), 10) || 0,
        variant: getComponentConfig(NAME, 'variant'),
        customClass: getComponentConfig(NAME, 'customClass')
      }; // Process `bindings.value`
  
      if (isString(bindings.value) || isNumber(bindings.value)) {
        // Value is popover content (html optionally supported)
        config.content = bindings.value;
      } else if (isFunction(bindings.value)) {
        // Content generator function
        config.content = bindings.value;
      } else if (isPlainObject(bindings.value)) {
        // Value is config object, so merge
        config = _objectSpread2({}, config, {}, bindings.value);
      } // If argument, assume element ID of container element
  
  
      if (bindings.arg) {
        // Element ID specified as arg
        // We must prepend '#' to become a CSS selector
        config.container = "#".concat(bindings.arg);
      } // If title is not provided, try title attribute
  
  
      if (isUndefined(config.title)) {
        // Try attribute
        var data = vnode.data || {};
        config.title = data.attrs && !isUndefinedOrNull(data.attrs.title) ? data.attrs.title : undefined;
      } // Normalize delay
  
  
      if (!isPlainObject(config.delay)) {
        config.delay = {
          show: parseInt(config.delay, 10) || 0,
          hide: parseInt(config.delay, 10) || 0
        };
      } // Process modifiers
  
  
      keys(bindings.modifiers).forEach(function (mod) {
        if (htmlRE.test(mod)) {
          // Title/content allows HTML
          config.html = true;
        } else if (noFadeRE.test(mod)) {
          // No animation
          config.animation = false;
        } else if (placementRE.test(mod)) {
          // Placement of popover
          config.placement = mod;
        } else if (boundaryRE.test(mod)) {
          // Boundary of popover
          mod = mod === 'scrollparent' ? 'scrollParent' : mod;
          config.boundary = mod;
        } else if (delayRE.test(mod)) {
          // Delay value
          var delay = parseInt(mod.slice(1), 10) || 0;
          config.delay.show = delay;
          config.delay.hide = delay;
        } else if (delayShowRE.test(mod)) {
          // Delay show value
          config.delay.show = parseInt(mod.slice(2), 10) || 0;
        } else if (delayHideRE.test(mod)) {
          // Delay hide value
          config.delay.hide = parseInt(mod.slice(2), 10) || 0;
        } else if (offsetRE.test(mod)) {
          // Offset value, negative allowed
          config.offset = parseInt(mod.slice(1), 10) || 0;
        } else if (variantRE.test(mod)) {
          // Variant
          config.variant = mod.slice(2) || null;
        }
      }); // Special handling of event trigger modifiers trigger is
      // a space separated list
  
      var selectedTriggers = {}; // Parse current config object trigger
  
      concat(config.trigger || '').filter(identity).join(' ').trim().toLowerCase().split(spacesRE).forEach(function (trigger) {
        if (validTriggers[trigger]) {
          selectedTriggers[trigger] = true;
        }
      }); // Parse modifiers for triggers
  
      keys(bindings.modifiers).forEach(function (mod) {
        mod = mod.toLowerCase();
  
        if (validTriggers[mod]) {
          // If modifier is a valid trigger
          selectedTriggers[mod] = true;
        }
      }); // Sanitize triggers
  
      config.trigger = keys(selectedTriggers).join(' ');
  
      if (config.trigger === 'blur') {
        // Blur by itself is useless, so convert it to 'focus'
        config.trigger = 'focus';
      }
  
      if (!config.trigger) {
        // Use default trigger
        config.trigger = DefaultTrigger;
      }
  
      return config;
    }; // Add or update Popover on our element
  
  
    var applyPopover = function applyPopover(el, bindings, vnode) {
      if (!isBrowser) {
        /* istanbul ignore next */
        return;
      }
  
      var config = parseBindings(bindings, vnode);
  
      if (!el[BV_POPOVER]) {
        var $parent = vnode.context;
        el[BV_POPOVER] = new BVPopover({
          parent: $parent,
          // Add the parent's scoped style attribute data
          _scopeId: getScopeId($parent, undefined)
        });
        el[BV_POPOVER].__bv_prev_data__ = {};
        el[BV_POPOVER].$on('show', function ()
        /* istanbul ignore next: for now */
        {
          // Before showing the popover, we update the title
          // and content if they are functions
          var data = {};
  
          if (isFunction(config.title)) {
            data.title = config.title(el);
          }
  
          if (isFunction(config.content)) {
            data.content = config.content(el);
          }
  
          if (keys(data).length > 0) {
            el[BV_POPOVER].updateData(data);
          }
        });
      }
  
      var data = {
        title: config.title,
        content: config.content,
        triggers: config.trigger,
        placement: config.placement,
        fallbackPlacement: config.fallbackPlacement,
        variant: config.variant,
        customClass: config.customClass,
        container: config.container,
        boundary: config.boundary,
        delay: config.delay,
        offset: config.offset,
        noFade: !config.animation,
        id: config.id,
        disabled: config.disabled,
        html: config.html
      };
      var oldData = el[BV_POPOVER].__bv_prev_data__;
      el[BV_POPOVER].__bv_prev_data__ = data;
  
      if (!looseEqual(data, oldData)) {
        // We only update the instance if data has changed
        var newData = {
          target: el
        };
        keys(data).forEach(function (prop) {
          // We only pass data properties that have changed
          if (data[prop] !== oldData[prop]) {
            // If title/content is a function, we execute it here
            newData[prop] = (prop === 'title' || prop === 'content') && isFunction(data[prop]) ? data[prop](el) : data[prop];
          }
        });
        el[BV_POPOVER].updateData(newData);
      }
    }; // Remove Popover from our element
  
  
    var removePopover = function removePopover(el) {
      if (el[BV_POPOVER]) {
        el[BV_POPOVER].$destroy();
        el[BV_POPOVER] = null;
      }
  
      delete el[BV_POPOVER];
    }; // Export our directive
  
  
    var VBPopover = {
      bind: function bind(el, bindings, vnode) {
        applyPopover(el, bindings, vnode);
      },
      // We use `componentUpdated` here instead of `update`, as the former
      // waits until the containing component and children have finished updating
      componentUpdated: function componentUpdated(el, bindings, vnode) {
        // Performed in a `$nextTick()` to prevent endless render/update loops
        vnode.context.$nextTick(function () {
          applyPopover(el, bindings, vnode);
        });
      },
      unbind: function unbind(el) {
        removePopover(el);
      }
    };
  
    var VBPopoverPlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBPopover: VBPopover
      }
    });
  
    var PopoverPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BPopover: BPopover
      },
      plugins: {
        VBPopoverPlugin: VBPopoverPlugin
      }
    });
  
    var NAME$B = 'BProgressBar'; // @vue/component
  
    var BProgressBar = /*#__PURE__*/Vue.extend({
      name: NAME$B,
      mixins: [normalizeSlotMixin],
      inject: {
        bvProgress: {
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: {
        value: {
          type: [Number, String],
          default: 0
        },
        label: {
          type: String,
          default: null
        },
        labelHtml: {
          type: String
        },
        // $parent (this.bvProgress) prop values may take precedence over the following props
        // Which is why they are defaulted to null
        max: {
          type: [Number, String],
          default: null
        },
        precision: {
          type: [Number, String],
          default: null
        },
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$B, 'variant');
          }
        },
        striped: {
          type: Boolean,
          default: null
        },
        animated: {
          type: Boolean,
          default: null
        },
        showProgress: {
          type: Boolean,
          default: null
        },
        showValue: {
          type: Boolean,
          default: null
        }
      },
      computed: {
        progressBarClasses: function progressBarClasses() {
          return [this.computedVariant ? "bg-".concat(this.computedVariant) : '', this.computedStriped || this.computedAnimated ? 'progress-bar-striped' : '', this.computedAnimated ? 'progress-bar-animated' : ''];
        },
        progressBarStyles: function progressBarStyles() {
          return {
            width: 100 * (this.computedValue / this.computedMax) + '%'
          };
        },
        computedValue: function computedValue() {
          return toFloat(this.value) || 0;
        },
        computedMax: function computedMax() {
          // Prefer our max over parent setting
          var max = toFloat(this.max);
          return isNaN(max) ? toFloat(this.bvProgress.max) || 100 : max;
        },
        computedPrecision: function computedPrecision() {
          // Prefer our precision over parent setting
          var precision = toInteger(this.precision);
          return isNaN(precision) ? toInteger(this.bvProgress.precision) || 0 : precision;
        },
        computedProgress: function computedProgress() {
          var precision = this.computedPrecision;
          var p = Math.pow(10, precision);
          return toFixed(100 * p * this.computedValue / this.computedMax / p, precision);
        },
        computedVariant: function computedVariant() {
          // Prefer our variant over parent setting
          return this.variant || this.bvProgress.variant;
        },
        computedStriped: function computedStriped() {
          // Prefer our striped over parent setting
          return isBoolean(this.striped) ? this.striped : this.bvProgress.striped || false;
        },
        computedAnimated: function computedAnimated() {
          // Prefer our animated over parent setting
          return isBoolean(this.animated) ? this.animated : this.bvProgress.animated || false;
        },
        computedShowProgress: function computedShowProgress() {
          // Prefer our showProgress over parent setting
          return isBoolean(this.showProgress) ? this.showProgress : this.bvProgress.showProgress || false;
        },
        computedShowValue: function computedShowValue() {
          // Prefer our showValue over parent setting
          return isBoolean(this.showValue) ? this.showValue : this.bvProgress.showValue || false;
        }
      },
      render: function render(h) {
        var childNodes = h();
  
        if (this.hasNormalizedSlot('default')) {
          childNodes = this.normalizeSlot('default');
        } else if (this.label || this.labelHtml) {
          childNodes = h('span', {
            domProps: htmlOrText(this.labelHtml, this.label)
          });
        } else if (this.computedShowProgress) {
          childNodes = this.computedProgress;
        } else if (this.computedShowValue) {
          childNodes = toFixed(this.computedValue, this.computedPrecision);
        }
  
        return h('div', {
          staticClass: 'progress-bar',
          class: this.progressBarClasses,
          style: this.progressBarStyles,
          attrs: {
            role: 'progressbar',
            'aria-valuemin': '0',
            'aria-valuemax': toString$1(this.computedMax),
            'aria-valuenow': toFixed(this.computedValue, this.computedPrecision)
          }
        }, [childNodes]);
      }
    });
  
    var NAME$C = 'BProgress'; // @vue/component
  
    var BProgress = /*#__PURE__*/Vue.extend({
      name: NAME$C,
      mixins: [normalizeSlotMixin],
      provide: function provide() {
        return {
          bvProgress: this
        };
      },
      props: {
        // These props can be inherited via the child b-progress-bar(s)
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$C, 'variant');
          }
        },
        striped: {
          type: Boolean,
          default: false
        },
        animated: {
          type: Boolean,
          default: false
        },
        height: {
          type: String,
          default: null
        },
        precision: {
          type: [Number, String],
          default: 0
        },
        showProgress: {
          type: Boolean,
          default: false
        },
        showValue: {
          type: Boolean,
          default: false
        },
        max: {
          type: [Number, String],
          default: 100
        },
        // This prop is not inherited by child b-progress-bar(s)
        value: {
          type: [Number, String],
          default: 0
        }
      },
      computed: {
        progressHeight: function progressHeight() {
          return {
            height: this.height || null
          };
        }
      },
      render: function render(h) {
        var childNodes = this.normalizeSlot('default');
  
        if (!childNodes) {
          childNodes = h(BProgressBar, {
            props: {
              value: this.value,
              max: this.max,
              precision: this.precision,
              variant: this.variant,
              animated: this.animated,
              striped: this.striped,
              showProgress: this.showProgress,
              showValue: this.showValue
            }
          });
        }
  
        return h('div', {
          class: ['progress'],
          style: this.progressHeight
        }, [childNodes]);
      }
    });
  
    var ProgressPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BProgress: BProgress,
        BProgressBar: BProgressBar
      }
    });
  
    var NAME$D = 'BSpinner'; // @vue/component
  
    var BSpinner = /*#__PURE__*/Vue.extend({
      name: NAME$D,
      functional: true,
      props: {
        type: {
          type: String,
          default: 'border' // SCSS currently supports 'border' or 'grow'
  
        },
        label: {
          type: String,
          default: null
        },
        variant: {
          type: String,
          default: function _default() {
            return getComponentConfig(NAME$D, 'variant');
          }
        },
        small: {
          type: Boolean,
          default: false
        },
        role: {
          type: String,
          default: 'status'
        },
        tag: {
          type: String,
          default: 'span'
        }
      },
      render: function render(h, _ref) {
        var _class;
  
        var props = _ref.props,
            data = _ref.data,
            slots = _ref.slots,
            scopedSlots = _ref.scopedSlots;
        var $slots = slots();
        var $scopedSlots = scopedSlots || {};
        var label = normalizeSlot('label', {}, $scopedSlots, $slots) || props.label;
  
        if (label) {
          label = h('span', {
            staticClass: 'sr-only'
          }, label);
        }
  
        return h(props.tag, a(data, {
          attrs: {
            role: label ? props.role || 'status' : null,
            'aria-hidden': label ? null : 'true'
          },
          class: (_class = {}, _defineProperty(_class, "spinner-".concat(props.type), props.type), _defineProperty(_class, "spinner-".concat(props.type, "-sm"), props.small), _defineProperty(_class, "text-".concat(props.variant), props.variant), _class)
        }), [label || h()]);
      }
    });
  
    var SpinnerPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BSpinner: BSpinner
      }
    });
  
    // Mixin to determine if an event listener has been registered
  
    var hasListenerMixin = {
      methods: {
        hasListener: function hasListener(name) {
          // Only includes listeners registerd via `v-on:name`
          var $listeners = this.$listeners || {}; // Includes `v-on:name` and `this.$on('name')` registerd listeners
          // Note this property is not part of the public Vue API, but it is
          // the only way to determine if a listener was added via `vm.$on`
  
          var $events = this._events || {}; // Registered listeners in `this._events` are always an array,
          // but might be zero length
  
          return !isUndefined($listeners[name]) || isArray($events[name]) && $events[name].length > 0;
        }
      }
    };
  
    /**
     * Converts a string, including strings in camelCase or snake_case, into Start Case (a variant
     * of Title Case where all words start with a capital letter), it keeps original single quote
     * and hyphen in the word.
     *
     * Copyright (c) 2017 Compass (MIT)
     * https://github.com/UrbanCompass/to-start-case
     * @author Zhuoyuan Zhang <https://github.com/drawyan>
     * @author Wei Wang <https://github.com/onlywei>
     *
     *
     *   'management_companies' to 'Management Companies'
     *   'managementCompanies' to 'Management Companies'
     *   `hell's kitchen` to `Hell's Kitchen`
     *   `co-op` to `Co-op`
     *
     * @param {String} str
     * @returns {String}
     */
    // Precompile regular expressions for performance
    var RX_UNDERSCORE = /_/g;
    var RX_LOWER_UPPER = /([a-z])([A-Z])/g;
    var RX_START_SPACE_WORD = /(\s|^)(\w)/g;
  
    var startCase = function startCase(str) {
      return str.replace(RX_UNDERSCORE, ' ').replace(RX_LOWER_UPPER, function (str, $1, $2) {
        return $1 + ' ' + $2;
      }).replace(RX_START_SPACE_WORD, function (str, $1, $2) {
        return $1 + $2.toUpperCase();
      });
    };
  
    // Constants used by table helpers
    // Object of item keys that should be ignored for headers and
    // stringification and filter events
    var IGNORED_FIELD_KEYS = {
      _rowVariant: true,
      _cellVariants: true,
      _showDetails: true
    }; // Filter CSS selector for click/dblclick/etc. events
    // If any of these selectors match the clicked element, we ignore the event
  
    var EVENT_FILTER = ['a', 'a *', // Include content inside links
    'button', 'button *', // Include content inside buttons
    'input:not(.disabled):not([disabled])', 'select:not(.disabled):not([disabled])', 'textarea:not(.disabled):not([disabled])', '[role="link"]', '[role="link"] *', '[role="button"]', '[role="button"] *', '[tabindex]:not(.disabled):not([disabled])'].join(',');
  
    var processField = function processField(key, value) {
      var field = null;
  
      if (isString(value)) {
        // Label shortcut
        field = {
          key: key,
          label: value
        };
      } else if (isFunction(value)) {
        // Formatter shortcut
        field = {
          key: key,
          formatter: value
        };
      } else if (isObject(value)) {
        field = clone(value);
        field.key = field.key || key;
      } else if (value !== false) {
        // Fallback to just key
  
        /* istanbul ignore next */
        field = {
          key: key
        };
      }
  
      return field;
    }; // We normalize fields into an array of objects
    // [ { key:..., label:..., ...}, {...}, ..., {..}]
  
  
    var normalizeFields = function normalizeFields(origFields, items) {
      var fields = [];
  
      if (isArray(origFields)) {
        // Normalize array Form
        origFields.filter(identity).forEach(function (f) {
          if (isString(f)) {
            fields.push({
              key: f,
              label: startCase(f)
            });
          } else if (isObject(f) && f.key && isString(f.key)) {
            // Full object definition. We use assign so that we don't mutate the original
            fields.push(clone(f));
          } else if (isObject(f) && keys(f).length === 1) {
            // Shortcut object (i.e. { 'foo_bar': 'This is Foo Bar' }
            var key = keys(f)[0];
            var field = processField(key, f[key]);
  
            if (field) {
              fields.push(field);
            }
          }
        });
      } // If no field provided, take a sample from first record (if exits)
  
  
      if (fields.length === 0 && isArray(items) && items.length > 0) {
        var sample = items[0];
        keys(sample).forEach(function (k) {
          if (!IGNORED_FIELD_KEYS[k]) {
            fields.push({
              key: k,
              label: startCase(k)
            });
          }
        });
      } // Ensure we have a unique array of fields and that they have String labels
  
  
      var memo = {};
      return fields.filter(function (f) {
        if (!memo[f.key]) {
          memo[f.key] = true;
          f.label = isString(f.label) ? f.label : startCase(f.key);
          return true;
        }
  
        return false;
      });
    };
  
    var itemsMixin = {
      props: {
        items: {
          // Provider mixin adds in `Function` type
          type: Array,
          default: function _default()
          /* istanbul ignore next */
          {
            return [];
          }
        },
        fields: {
          type: Array,
          default: null
        },
        primaryKey: {
          // Primary key for record
          // If provided the value in each row must be unique!
          type: String,
          default: null
        },
        value: {
          // `v-model` for retrieving the current displayed rows
          type: Array,
          default: function _default() {
            return [];
          }
        }
      },
      data: function data() {
        return {
          // Our local copy of the items
          // Must be an array
          localItems: isArray(this.items) ? this.items.slice() : []
        };
      },
      computed: {
        computedFields: function computedFields() {
          // We normalize fields into an array of objects
          // `[ { key:..., label:..., ...}, {...}, ..., {..}]`
          return normalizeFields(this.fields, this.localItems);
        },
        computedFieldsObj: function computedFieldsObj() {
          // Fields as a simple lookup hash object
          // Mainly for formatter lookup and use in `scopedSlots` for convenience
          // If the field has a formatter, it normalizes formatter to a
          // function ref or `undefined` if no formatter
          var parent = this.$parent;
          return this.computedFields.reduce(function (obj, f) {
            // We use object spread here so we don't mutate the original field object
            obj[f.key] = clone(f);
  
            if (f.formatter) {
              // Normalize formatter to a function ref or `undefined`
              var formatter = f.formatter;
  
              if (isString(formatter) && isFunction(parent[formatter])) {
                formatter = parent[formatter];
              } else if (!isFunction(formatter)) {
                /* istanbul ignore next */
                formatter = undefined;
              } // Return formatter function or `undefined` if none
  
  
              obj[f.key].formatter = formatter;
            }
  
            return obj;
          }, {});
        },
        computedItems: function computedItems() {
          // Fallback if various mixins not provided
          return (this.paginatedItems || this.sortedItems || this.filteredItems || this.localItems || []).slice();
        },
        context: function context() {
          // Current state of sorting, filtering and pagination props/values
          return {
            filter: this.localFilter,
            sortBy: this.localSortBy,
            sortDesc: this.localSortDesc,
            perPage: parseInt(this.perPage, 10) || 0,
            currentPage: parseInt(this.currentPage, 10) || 1,
            apiUrl: this.apiUrl
          };
        }
      },
      watch: {
        items: function items(newItems) {
          /* istanbul ignore else */
          if (isArray(newItems)) {
            // Set `localItems`/`filteredItems` to a copy of the provided array
            this.localItems = newItems.slice();
          } else if (isUndefinedOrNull(newItems)) {
            /* istanbul ignore next */
            this.localItems = [];
          }
        },
        // Watch for changes on `computedItems` and update the `v-model`
        computedItems: function computedItems(newVal) {
          this.$emit('input', newVal);
        },
        // Watch for context changes
        context: function context(newVal, oldVal) {
          // Emit context information for external paging/filtering/sorting handling
          if (!looseEqual(newVal, oldVal)) {
            this.$emit('context-changed', newVal);
          }
        }
      },
      mounted: function mounted() {
        // Initially update the `v-model` of displayed items
        this.$emit('input', this.computedItems);
      },
      methods: {
        // Method to get the formatter method for a given field key
        getFieldFormatter: function getFieldFormatter(key) {
          var field = this.computedFieldsObj[key]; // `this.computedFieldsObj` has pre-normalized the formatter to a
          // function ref if present, otherwise `undefined`
  
          return field ? field.formatter : undefined;
        }
      }
    };
  
    // Mixin for providing stacked tables
    var stackedMixin = {
      props: {
        stacked: {
          type: [Boolean, String],
          default: false
        }
      },
      computed: {
        isStacked: function isStacked() {
          // `true` when always stacked, or returns breakpoint specified
          return this.stacked === '' ? true : this.stacked;
        },
        isStackedAlways: function isStackedAlways() {
          return this.isStacked === true;
        },
        stackedTableClasses: function stackedTableClasses() {
          return _defineProperty({
            'b-table-stacked': this.isStackedAlways
          }, "b-table-stacked-".concat(this.stacked), !this.isStackedAlways && this.isStacked);
        }
      }
    };
  
    var sanitizeRow = function sanitizeRow(row, ignoreFields, includeFields) {
      var fieldsObj = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
      return keys(row).reduce(function (obj, key) {
        // Ignore special fields that start with `_`
        // Ignore fields in the `ignoreFields` array
        // Include only fields in the `includeFields` array
        if (!IGNORED_FIELD_KEYS[key] && !(ignoreFields && ignoreFields.length > 0 && arrayIncludes(ignoreFields, key)) && !(includeFields && includeFields.length > 0 && !arrayIncludes(includeFields, key))) {
          var f = fieldsObj[key] || {};
          var val = row[key]; // `f.filterByFormatted` will either be a function or boolean
          // `f.formater` will have already been noramlized into a function ref
  
          var filterByFormatted = f.filterByFormatted;
          var formatter = isFunction(filterByFormatted) ? filterByFormatted : filterByFormatted ? f.formatter : null;
          obj[key] = isFunction(formatter) ? formatter(val, key, row) : val;
        }
  
        return obj;
      }, {});
    };
  
    // SSR safe deterministic way (keys are sorted before stringification)
    //
    //   ex:
    //     { b: 3, c: { z: 'zzz', d: null, e: 2 }, d: [10, 12, 11], a: 'one' }
    //   becomes
    //     'one 3 2 zzz 10 12 11'
    //
    // Primitives (numbers/strings) are returned as-is
    // Null and undefined values are filtered out
    // Dates are converted to their native string format
  
    var stringifyObjectValues = function stringifyObjectValues(val) {
      if (isUndefinedOrNull(val)) {
        /* istanbul ignore next */
        return '';
      } // Arrays are also object, and keys just returns the array indexes
      // Date objects we convert to strings
  
  
      if (isObject(val) && !isDate(val)) {
        return keys(val).sort() // Sort to prevent SSR issues on pre-rendered sorted tables
        .filter(function (v) {
          return !isUndefinedOrNull(v);
        }) // Ignore undefined/null values
        .map(function (k) {
          return stringifyObjectValues(val[k]);
        }).join(' ');
      }
  
      return toString$1(val);
    };
  
    // TODO: Add option to stringify `scopedSlot` items
  
    var stringifyRecordValues = function stringifyRecordValues(row, ignoreFields, includeFields, fieldsObj) {
      return isObject(row) ? stringifyObjectValues(sanitizeRow(row, ignoreFields, includeFields, fieldsObj)) : '';
    };
  
    var DEBOUNCE_DEPRECATED_MSG = 'Prop "filter-debounce" is deprecated. Use the debounce feature of "<b-form-input>" instead.';
    var RX_SPACES$1 = /[\s\uFEFF\xA0]+/g;
    var filteringMixin = {
      props: {
        filter: {
          type: [String, RegExp, Object, Array],
          default: null
        },
        filterFunction: {
          type: Function,
          default: null
        },
        filterIgnoredFields: {
          type: Array // default: undefined
  
        },
        filterIncludedFields: {
          type: Array // default: undefined
  
        },
        filterDebounce: {
          type: [Number, String],
          deprecated: DEBOUNCE_DEPRECATED_MSG,
          default: 0,
          validator: function validator(val) {
            return /^\d+/.test(String(val));
          }
        }
      },
      data: function data() {
        return {
          // Flag for displaying which empty slot to show and some event triggering
          isFiltered: false,
          // Where we store the copy of the filter criteria after debouncing
          // We pre-set it with the sanitized filter value
          localFilter: this.filterSanitize(this.filter)
        };
      },
      computed: {
        computedFilterIgnored: function computedFilterIgnored() {
          return this.filterIgnoredFields ? concat(this.filterIgnoredFields).filter(Boolean) : null;
        },
        computedFilterIncluded: function computedFilterIncluded() {
          return this.filterIncludedFields ? concat(this.filterIncludedFields).filter(Boolean) : null;
        },
        computedFilterDebounce: function computedFilterDebounce() {
          var ms = toInteger(this.filterDebounce) || 0;
          /* istanbul ignore next */
  
          if (ms > 0) {
            warn(DEBOUNCE_DEPRECATED_MSG, 'BTable');
          }
  
          return ms;
        },
        localFiltering: function localFiltering() {
          return this.hasProvider ? !!this.noProviderFiltering : true;
        },
        // For watching changes to `filteredItems` vs `localItems`
        filteredCheck: function filteredCheck() {
          return {
            filteredItems: this.filteredItems,
            localItems: this.localItems,
            localFilter: this.localFilter
          };
        },
        // Sanitized/normalize filter-function prop
        localFilterFn: function localFilterFn() {
          // Return `null` to signal to use internal filter function
          return isFunction(this.filterFunction) ? this.filterFunction : null;
        },
        // Returns the records in `localItems` that match the filter criteria
        // Returns the original `localItems` array if not sorting
        filteredItems: function filteredItems() {
          var items = this.localItems || []; // Note the criteria is debounced and sanitized
  
          var criteria = this.localFilter; // Resolve the filtering function, when requested
          // We prefer the provided filtering function and fallback to the internal one
          // When no filtering criteria is specified the filtering factories will return `null`
  
          var filterFn = this.localFiltering ? this.filterFnFactory(this.localFilterFn, criteria) || this.defaultFilterFnFactory(criteria) : null; // We only do local filtering when requested and there are records to filter
  
          return filterFn && items.length > 0 ? items.filter(filterFn) : items;
        }
      },
      watch: {
        // Watch for debounce being set to 0
        computedFilterDebounce: function computedFilterDebounce(newVal) {
          if (!newVal && this.$_filterTimer) {
            clearTimeout(this.$_filterTimer);
            this.$_filterTimer = null;
            this.localFilter = this.filterSanitize(this.filter);
          }
        },
        // Watch for changes to the filter criteria, and debounce if necessary
        filter: {
          // We need a deep watcher in case the user passes
          // an object when using `filter-function`
          deep: true,
          handler: function handler(newCriteria) {
            var _this = this;
  
            var timeout = this.computedFilterDebounce;
            clearTimeout(this.$_filterTimer);
            this.$_filterTimer = null;
  
            if (timeout && timeout > 0) {
              // If we have a debounce time, delay the update of `localFilter`
              this.$_filterTimer = setTimeout(function () {
                _this.localFilter = _this.filterSanitize(newCriteria);
              }, timeout);
            } else {
              // Otherwise, immediately update `localFilter` with `newFilter` value
              this.localFilter = this.filterSanitize(newCriteria);
            }
          }
        },
        // Watch for changes to the filter criteria and filtered items vs `localItems`
        // Set visual state and emit events as required
        filteredCheck: function filteredCheck(_ref) {
          var filteredItems = _ref.filteredItems,
              localFilter = _ref.localFilter;
          // Determine if the dataset is filtered or not
          var isFiltered = false;
  
          if (!localFilter) {
            // If filter criteria is falsey
            isFiltered = false;
          } else if (looseEqual(localFilter, []) || looseEqual(localFilter, {})) {
            // If filter criteria is an empty array or object
            isFiltered = false;
          } else if (localFilter) {
            // If filter criteria is truthy
            isFiltered = true;
          }
  
          if (isFiltered) {
            this.$emit('filtered', filteredItems, filteredItems.length);
          }
  
          this.isFiltered = isFiltered;
        },
        isFiltered: function isFiltered(newVal, oldVal) {
          if (newVal === false && oldVal === true) {
            // We need to emit a filtered event if isFiltered transitions from true to
            // false so that users can update their pagination controls.
            this.$emit('filtered', this.localItems, this.localItems.length);
          }
        }
      },
      created: function created() {
        var _this2 = this;
  
        // Create non-reactive prop where we store the debounce timer id
        this.$_filterTimer = null; // If filter is "pre-set", set the criteria
        // This will trigger any watchers/dependents
        // this.localFilter = this.filterSanitize(this.filter)
        // Set the initial filtered state in a `$nextTick()` so that
        // we trigger a filtered event if needed
  
        this.$nextTick(function () {
          _this2.isFiltered = Boolean(_this2.localFilter);
        });
      },
      beforeDestroy: function beforeDestroy()
      /* istanbul ignore next */
      {
        clearTimeout(this.$_filterTimer);
        this.$_filterTimer = null;
      },
      methods: {
        filterSanitize: function filterSanitize(criteria) {
          // Sanitizes filter criteria based on internal or external filtering
          if (this.localFiltering && !this.localFilterFn && !(isString(criteria) || isRegExp(criteria))) {
            // If using internal filter function, which only accepts string or RegExp,
            // return '' to signify no filter
            return '';
          } // Could be a string, object or array, as needed by external filter function
          // We use `cloneDeep` to ensure we have a new copy of an object or array
          // without Vue's reactive observers
  
  
          return cloneDeep(criteria);
        },
        // Filter Function factories
        filterFnFactory: function filterFnFactory(filterFn, criteria) {
          // Wrapper factory for external filter functions
          // Wrap the provided filter-function and return a new function
          // Returns `null` if no filter-function defined or if criteria is falsey
          // Rather than directly grabbing `this.computedLocalFilterFn` or `this.filterFunction`
          // we have it passed, so that the caller computed prop will be reactive to changes
          // in the original filter-function (as this routine is a method)
          if (!filterFn || !isFunction(filterFn) || !criteria || looseEqual(criteria, []) || looseEqual(criteria, {})) {
            return null;
          } // Build the wrapped filter test function, passing the criteria to the provided function
  
  
          var fn = function fn(item) {
            // Generated function returns true if the criteria matches part
            // of the serialized data, otherwise false
            return filterFn(item, criteria);
          }; // Return the wrapped function
  
  
          return fn;
        },
        defaultFilterFnFactory: function defaultFilterFnFactory(criteria) {
          var _this3 = this;
  
          // Generates the default filter function, using the given filter criteria
          // Returns `null` if no criteria or criteria format not supported
          if (!criteria || !(isString(criteria) || isRegExp(criteria))) {
            // Built in filter can only support strings or RegExp criteria (at the moment)
            return null;
          } // Build the RegExp needed for filtering
  
  
          var regExp = criteria;
  
          if (isString(regExp)) {
            // Escape special RegExp characters in the string and convert contiguous
            // whitespace to \s+ matches
            var pattern = escapeRegExp(criteria).replace(RX_SPACES$1, '\\s+'); // Build the RegExp (no need for global flag, as we only need
            // to find the value once in the string)
  
            regExp = new RegExp(".*".concat(pattern, ".*"), 'i');
          } // Generate the wrapped filter test function to use
  
  
          var fn = function fn(item) {
            // This searches all row values (and sub property values) in the entire (excluding
            // special `_` prefixed keys), because we convert the record to a space-separated
            // string containing all the value properties (recursively), even ones that are
            // not visible (not specified in this.fields)
            // Users can ignore filtering on specific fields, or on only certain fields,
            // and can optionall specify searching results of fields with formatter
            //
            // TODO: Enable searching on scoped slots (optional, as it will be SLOW)
            //
            // Generated function returns true if the criteria matches part of
            // the serialized data, otherwise false
            //
            // We set `lastIndex = 0` on the `RegExp` in case someone specifies the `/g` global flag
            regExp.lastIndex = 0;
            return regExp.test(stringifyRecordValues(item, _this3.computedFilterIgnored, _this3.computedFilterIncluded, _this3.computedFieldsObj));
          }; // Return the generated function
  
  
          return fn;
        }
      }
    };
  
    /*
     * Consistent and stable sort function across JavaScript platforms
     *
     * Inconsistent sorts can cause SSR problems between client and server
     * such as in <b-table> if sortBy is applied to the data on server side render.
     * Chrome and V8 native sorts are inconsistent/unstable
     *
     * This function uses native sort with fallback to index compare when the a and b
     * compare returns 0
     *
     * Algorithm based on:
     * https://stackoverflow.com/questions/1427608/fast-stable-sorting-algorithm-implementation-in-javascript/45422645#45422645
     *
     * @param {array} array to sort
     * @param {function} sort compare function
     * @return {array}
     */
    var stableSort = function stableSort(array, compareFn) {
      // Using `.bind(compareFn)` on the wrapped anonymous function improves
      // performance by avoiding the function call setup. We don't use an arrow
      // function here as it binds `this` to the `stableSort` context rather than
      // the `compareFn` context, which wouldn't give us the performance increase.
      return array.map(function (a, index) {
        return [index, a];
      }).sort(function (a, b) {
        return this(a[1], b[1]) || a[0] - b[0];
      }.bind(compareFn)).map(function (e) {
        return e[1];
      });
    };
  
    //
    // TODO: Add option to sort by multiple columns (tri-state per column,
    //       plus order of columns in sort)  where sortBy could be an array
    //       of objects `[ {key: 'foo', sortDir: 'asc'}, {key:'bar', sortDir: 'desc'} ...]`
    //       or an array of arrays `[ ['foo','asc'], ['bar','desc'] ]`
    //       Multisort will most likely be handled in mixin-sort.js by
    //       calling this method for each sortBy
  
    var defaultSortCompare = function defaultSortCompare(a, b, sortBy, sortDesc, formatter, localeOpts, locale, nullLast) {
      var aa = get(a, sortBy, null);
      var bb = get(b, sortBy, null);
  
      if (isFunction(formatter)) {
        aa = formatter(aa, sortBy, a);
        bb = formatter(bb, sortBy, b);
      }
  
      aa = isUndefinedOrNull(aa) ? '' : aa;
      bb = isUndefinedOrNull(bb) ? '' : bb;
  
      if (isDate(aa) && isDate(bb) || isNumber(aa) && isNumber(bb)) {
        // Special case for comparing dates and numbers
        // Internally dates are compared via their epoch number values
        return aa < bb ? -1 : aa > bb ? 1 : 0;
      } else if (nullLast && aa === '' && bb !== '') {
        // Special case when sorting null/undefined/empty string last
        return 1;
      } else if (nullLast && aa !== '' && bb === '') {
        // Special case when sorting null/undefined/empty string last
        return -1;
      } // Do localized string comparison
  
  
      return stringifyObjectValues(aa).localeCompare(stringifyObjectValues(bb), locale, localeOpts);
    };
  
    var sortingMixin = {
      props: {
        sortBy: {
          type: String,
          default: ''
        },
        sortDesc: {
          // TODO: Make this tri-state: true, false, null
          type: Boolean,
          default: false
        },
        sortDirection: {
          // This prop is named incorrectly
          // It should be `initialSortDirection` as it is a bit misleading
          // (not to mention it screws up the ARIA label on the headers)
          type: String,
          default: 'asc',
          validator: function validator(direction) {
            return arrayIncludes(['asc', 'desc', 'last'], direction);
          }
        },
        sortCompare: {
          type: Function,
          default: null
        },
        sortCompareOptions: {
          // Supported localCompare options, see `options` section of:
          // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
          type: Object,
          default: function _default() {
            return {
              numeric: true
            };
          }
        },
        sortCompareLocale: {
          // String: locale code
          // Array: array of Locale strings
          type: [String, Array] // default: undefined
  
        },
        sortNullLast: {
          // Sort null and undefined to appear last
          type: Boolean,
          default: false
        },
        noSortReset: {
          // Another prop that should have had a better name.
          // It should be noSortClear (on non-sortable headers).
          // We will need to make sure the documentation is clear on what
          // this prop does (as well as in the code for future reference)
          type: Boolean,
          default: false
        },
        labelSortAsc: {
          type: String,
          default: 'Click to sort Ascending'
        },
        labelSortDesc: {
          type: String,
          default: 'Click to sort Descending'
        },
        labelSortClear: {
          type: String,
          default: 'Click to clear sorting'
        },
        noLocalSorting: {
          type: Boolean,
          default: false
        },
        noFooterSorting: {
          type: Boolean,
          default: false
        },
        sortIconLeft: {
          // Place the sorting icon on the left of the header cells
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          localSortBy: this.sortBy || '',
          localSortDesc: this.sortDesc || false
        };
      },
      computed: {
        localSorting: function localSorting() {
          return this.hasProvider ? !!this.noProviderSorting : !this.noLocalSorting;
        },
        isSortable: function isSortable() {
          return this.computedFields.some(function (f) {
            return f.sortable;
          });
        },
        sortedItems: function sortedItems() {
          // Sorts the filtered items and returns a new array of the sorted items
          // or the original items array if not sorted.
          var items = (this.filteredItems || this.localItems || []).slice();
          var sortBy = this.localSortBy;
          var sortDesc = this.localSortDesc;
          var sortCompare = this.sortCompare;
          var localSorting = this.localSorting;
  
          var sortOptions = _objectSpread2({}, this.sortCompareOptions, {
            usage: 'sort'
          });
  
          var sortLocale = this.sortCompareLocale || undefined;
          var nullLast = this.sortNullLast;
  
          if (sortBy && localSorting) {
            var field = this.computedFieldsObj[sortBy] || {};
            var sortByFormatted = field.sortByFormatted;
            var formatter = isFunction(sortByFormatted) ? sortByFormatted : sortByFormatted ? this.getFieldFormatter(sortBy) : undefined; // `stableSort` returns a new array, and leaves the original array intact
  
            return stableSort(items, function (a, b) {
              var result = null;
  
              if (isFunction(sortCompare)) {
                // Call user provided sortCompare routine
                result = sortCompare(a, b, sortBy, sortDesc, formatter, sortOptions, sortLocale);
              }
  
              if (isUndefinedOrNull(result) || result === false) {
                // Fallback to built-in defaultSortCompare if sortCompare
                // is not defined or returns null/false
                result = defaultSortCompare(a, b, sortBy, sortDesc, formatter, sortOptions, sortLocale, nullLast);
              } // Negate result if sorting in descending order
  
  
              return (result || 0) * (sortDesc ? -1 : 1);
            });
          }
  
          return items;
        }
      },
      watch: {
        isSortable: function isSortable(newVal)
        /* istanbul ignore next: pain in the butt to test */
        {
          if (newVal) {
            if (this.isSortable) {
              this.$on('head-clicked', this.handleSort);
            }
          } else {
            this.$off('head-clicked', this.handleSort);
          }
        },
        sortDesc: function sortDesc(newVal) {
          if (newVal === this.localSortDesc) {
            /* istanbul ignore next */
            return;
          }
  
          this.localSortDesc = newVal || false;
        },
        sortBy: function sortBy(newVal) {
          if (newVal === this.localSortBy) {
            /* istanbul ignore next */
            return;
          }
  
          this.localSortBy = newVal || '';
        },
        // Update .sync props
        localSortDesc: function localSortDesc(newVal, oldVal) {
          // Emit update to sort-desc.sync
          if (newVal !== oldVal) {
            this.$emit('update:sortDesc', newVal);
          }
        },
        localSortBy: function localSortBy(newVal, oldVal) {
          if (newVal !== oldVal) {
            this.$emit('update:sortBy', newVal);
          }
        }
      },
      created: function created() {
        if (this.isSortable) {
          this.$on('head-clicked', this.handleSort);
        }
      },
      methods: {
        // Handlers
        // Need to move from thead-mixin
        handleSort: function handleSort(key, field, evt, isFoot) {
          var _this = this;
  
          if (!this.isSortable) {
            /* istanbul ignore next */
            return;
          }
  
          if (isFoot && this.noFooterSorting) {
            return;
          } // TODO: make this tri-state sorting
          // cycle desc => asc => none => desc => ...
  
  
          var sortChanged = false;
  
          var toggleLocalSortDesc = function toggleLocalSortDesc() {
            var sortDirection = field.sortDirection || _this.sortDirection;
  
            if (sortDirection === 'asc') {
              _this.localSortDesc = false;
            } else if (sortDirection === 'desc') {
              _this.localSortDesc = true;
            }
          };
  
          if (field.sortable) {
            if (key === this.localSortBy) {
              // Change sorting direction on current column
              this.localSortDesc = !this.localSortDesc;
            } else {
              // Start sorting this column ascending
              this.localSortBy = key; // this.localSortDesc = false
  
              toggleLocalSortDesc();
            }
  
            sortChanged = true;
          } else if (this.localSortBy && !this.noSortReset) {
            this.localSortBy = '';
            toggleLocalSortDesc();
            sortChanged = true;
          }
  
          if (sortChanged) {
            // Sorting parameters changed
            this.$emit('sort-changed', this.context);
          }
        },
        // methods to compute classes and attrs for thead>th cells
        sortTheadThClasses: function sortTheadThClasses(key, field, isFoot) {
          return {
            // If sortable and sortIconLeft are true, then place sort icon on the left
            'b-table-sort-icon-left': field.sortable && this.sortIconLeft && !(isFoot && this.noFooterSorting)
          };
        },
        sortTheadThAttrs: function sortTheadThAttrs(key, field, isFoot) {
          if (!this.isSortable || isFoot && this.noFooterSorting) {
            // No attributes if not a sortable table
            return {};
          }
  
          var sortable = field.sortable; // Assemble the aria-sort attribute value
  
          var ariaSort = sortable && this.localSortBy === key ? this.localSortDesc ? 'descending' : 'ascending' : sortable ? 'none' : null; // Return the attribute
  
          return {
            'aria-sort': ariaSort
          };
        },
        sortTheadThLabel: function sortTheadThLabel(key, field, isFoot) {
          // A label to be placed in an `.sr-only` element in the header cell
          if (!this.isSortable || isFoot && this.noFooterSorting) {
            // No label if not a sortable table
            return null;
          }
  
          var sortable = field.sortable; // The correctness of these labels is very important for screen-reader users.
  
          var labelSorting = '';
  
          if (sortable) {
            if (this.localSortBy === key) {
              // currently sorted sortable column.
              labelSorting = this.localSortDesc ? this.labelSortAsc : this.labelSortDesc;
            } else {
              // Not currently sorted sortable column.
              // Not using nested ternary's here for clarity/readability
              // Default for ariaLabel
              labelSorting = this.localSortDesc ? this.labelSortDesc : this.labelSortAsc; // Handle sortDirection setting
  
              var sortDirection = this.sortDirection || field.sortDirection;
  
              if (sortDirection === 'asc') {
                labelSorting = this.labelSortAsc;
              } else if (sortDirection === 'desc') {
                labelSorting = this.labelSortDesc;
              }
            }
          } else if (!this.noSortReset) {
            // Non sortable column
            labelSorting = this.localSortBy ? this.labelSortClear : '';
          } // Return the sr-only sort label or null if no label
  
  
          return trim(labelSorting) || null;
        }
      }
    };
  
    var paginationMixin$1 = {
      props: {
        perPage: {
          type: [Number, String],
          default: 0
        },
        currentPage: {
          type: [Number, String],
          default: 1
        }
      },
      computed: {
        localPaging: function localPaging() {
          return this.hasProvider ? !!this.noProviderPaging : true;
        },
        paginatedItems: function paginatedItems() {
          var items = this.sortedItems || this.filteredItems || this.localItems || [];
          var currentPage = Math.max(parseInt(this.currentPage, 10) || 1, 1);
          var perPage = Math.max(parseInt(this.perPage, 10) || 0, 0); // Apply local pagination
  
          if (this.localPaging && !!perPage) {
            // Grab the current page of data (which may be past filtered items limit)
            items = items.slice((currentPage - 1) * perPage, currentPage * perPage);
          } // Return the items to display in the table
  
  
          return items;
        }
      }
    };
  
    var captionMixin = {
      props: {
        // `caption-top` is part of table-redere mixin (styling)
        // captionTop: {
        //   type: Boolean,
        //   default: false
        // },
        caption: {
          type: String,
          default: null
        },
        captionHtml: {
          type: String
        }
      },
      computed: {
        captionId: function captionId() {
          // Even though `this.safeId` looks like a method, it is a computed prop
          // that returns a new function if the underlying ID changes
          return this.isStacked ? this.safeId('_caption_') : null;
        }
      },
      methods: {
        renderCaption: function renderCaption() {
          var h = this.$createElement; // Build the caption
  
          var $captionSlot = this.normalizeSlot('table-caption');
          var $caption = h();
  
          if ($captionSlot || this.caption || this.captionHtml) {
            var data = {
              key: 'caption',
              attrs: {
                id: this.captionId
              }
            };
  
            if (!$captionSlot) {
              data.domProps = htmlOrText(this.captionHtml, this.caption);
            }
  
            $caption = h('caption', data, [$captionSlot]);
          }
  
          return $caption;
        }
      }
    };
  
    var colgroupMixin = {
      methods: {
        renderColgroup: function renderColgroup() {
          var h = this.$createElement;
          var fields = this.computedFields;
          var $colgroup = h();
  
          if (this.hasNormalizedSlot('table-colgroup')) {
            $colgroup = h('colgroup', {
              key: 'colgroup'
            }, [this.normalizeSlot('table-colgroup', {
              columns: fields.length,
              fields: fields
            })]);
          }
  
          return $colgroup;
        }
      }
    };
  
    var TABLE_TAG_NAMES = ['TD', 'TH', 'TR']; // Returns `true` if we should ignore the click/double-click/keypress event
    // Avoids having the user need to use `@click.stop` on the form control
  
    var filterEvent = function filterEvent(evt) {
      // Exit early when we don't have a target element
      if (!evt || !evt.target) {
        /* istanbul ignore next */
        return false;
      }
  
      var el = evt.target; // Exit early when element is disabled or a table element
  
      if (el.disabled || TABLE_TAG_NAMES.indexOf(el.tagName) !== -1) {
        return false;
      } // Ignore the click when it was inside a dropdown menu
  
  
      if (closest('.dropdown-menu', el)) {
        return true;
      }
  
      var label = el.tagName === 'LABEL' ? el : closest('label', el); // If the label's form control is not disabled then we don't propagate event
      // Modern browsers have `label.control` that references the associated input, but IE 11
      // does not have this property on the label element, so we resort to DOM lookups
  
      if (label) {
        var labelFor = getAttr(label, 'for');
        var input = labelFor ? getById(labelFor) : select('input, select, textarea', label);
  
        if (input && !input.disabled) {
          return true;
        }
      } // Otherwise check if the event target matches one of the selectors in the
      // event filter (i.e. anchors, non disabled inputs, etc.)
      // Return `true` if we should ignore the event
  
  
      return matches(el, EVENT_FILTER);
    };
  
    // Used to filter out click events caused by the mouse up at end of selection
    //
    // Accepts an element as only argument to test to see if selection overlaps or is
    // contained within the element
  
    var textSelectionActive = function textSelectionActive() {
      var el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;
      var sel = getSel();
      return sel && sel.toString().trim() !== '' && sel.containsNode && isElement(el) ? sel.containsNode(el, true) : false;
    };
  
    var props$T = {
      headVariant: {
        // Also sniffed by <b-tr> / <b-td> / <b-th>
        type: String,
        // supported values: 'lite', 'dark', or null
        default: null
      }
    }; // @vue/component
  
    var BThead = /*#__PURE__*/Vue.extend({
      name: 'BThead',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      provide: function provide() {
        return {
          bvTableRowGroup: this
        };
      },
      inject: {
        bvTable: {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: props$T,
      computed: {
        isThead: function isThead() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return true;
        },
        isDark: function isDark() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.dark;
        },
        isStacked: function isStacked() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.isStacked;
        },
        isResponsive: function isResponsive() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.isResponsive;
        },
        isStickyHeader: function isStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          // Sticky headers only apply to cells in table `thead`
          return !this.isStacked && this.bvTable.stickyHeader;
        },
        hasStickyHeader: function hasStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          return !this.isStacked && this.bvTable.stickyHeader;
        },
        tableVariant: function tableVariant() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.tableVariant;
        },
        theadClasses: function theadClasses() {
          return [this.headVariant ? "thead-".concat(this.headVariant) : null];
        },
        theadAttrs: function theadAttrs() {
          return _objectSpread2({
            role: 'rowgroup'
          }, this.$attrs);
        }
      },
      render: function render(h) {
        return h('thead', {
          class: this.theadClasses,
          attrs: this.theadAttrs,
          // Pass down any native listeners
          on: this.$listeners
        }, this.normalizeSlot('default'));
      }
    });
  
    var props$U = {
      footVariant: {
        type: String,
        // supported values: 'lite', 'dark', or null
        default: null
      }
    }; // @vue/component
  
    var BTfoot = /*#__PURE__*/Vue.extend({
      name: 'BTfoot',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      provide: function provide() {
        return {
          bvTableRowGroup: this
        };
      },
      inject: {
        bvTable: {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: props$U,
      computed: {
        isTfoot: function isTfoot() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return true;
        },
        isDark: function isDark()
        /* istanbul ignore next: Not currently sniffed in tests */
        {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.dark;
        },
        isStacked: function isStacked() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.isStacked;
        },
        isResponsive: function isResponsive() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.isResponsive;
        },
        isStickyHeader: function isStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Sticky headers are only supported in thead
          return false;
        },
        hasStickyHeader: function hasStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          return !this.isStacked && this.bvTable.stickyHeader;
        },
        tableVariant: function tableVariant()
        /* istanbul ignore next: Not currently sniffed in tests */
        {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.tableVariant;
        },
        tfootClasses: function tfootClasses() {
          return [this.footVariant ? "thead-".concat(this.footVariant) : null];
        },
        tfootAttrs: function tfootAttrs() {
          return _objectSpread2({
            role: 'rowgroup'
          }, this.$attrs);
        }
      },
      render: function render(h) {
        return h('tfoot', {
          class: this.tfootClasses,
          attrs: this.tfootAttrs,
          // Pass down any native listeners
          on: this.$listeners
        }, this.normalizeSlot('default'));
      }
    });
  
    var props$V = {
      variant: {
        type: String,
        default: null
      }
    };
    var LIGHT = 'light';
    var DARK = 'dark'; // @vue/component
  
    var BTr = /*#__PURE__*/Vue.extend({
      name: 'BTr',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      provide: function provide() {
        return {
          bvTableTr: this
        };
      },
      inject: {
        bvTableRowGroup: {
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: props$V,
      computed: {
        inTbody: function inTbody() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.isTbody;
        },
        inThead: function inThead() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.isThead;
        },
        inTfoot: function inTfoot() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.isTfoot;
        },
        isDark: function isDark() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.isDark;
        },
        isStacked: function isStacked() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.isStacked;
        },
        isResponsive: function isResponsive() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.isResponsive;
        },
        isStickyHeader: function isStickyHeader() {
          // Sniffed by <b-td> / <b-th>
          // Sticky headers are only supported in thead
          return this.bvTableRowGroup.isStickyHeader;
        },
        hasStickyHeader: function hasStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          return !this.isStacked && this.bvTableRowGroup.hasStickyHeader;
        },
        tableVariant: function tableVariant() {
          // Sniffed by <b-td> / <b-th>
          return this.bvTableRowGroup.tableVariant;
        },
        headVariant: function headVariant() {
          // Sniffed by <b-td> / <b-th>
          return this.inThead ? this.bvTableRowGroup.headVariant : null;
        },
        footVariant: function footVariant() {
          // Sniffed by <b-td> / <b-th>
          return this.inTfoot ? this.bvTableRowGroup.footVariant : null;
        },
        isRowDark: function isRowDark() {
          return this.headVariant === LIGHT || this.footVariant === LIGHT ? false : this.headVariant === DARK || this.footVariant === DARK ? true : this.isDark;
        },
        trClasses: function trClasses() {
          return [this.variant ? "".concat(this.isRowDark ? 'bg' : 'table', "-").concat(this.variant) : null];
        },
        trAttrs: function trAttrs() {
          return _objectSpread2({
            role: 'row'
          }, this.$attrs);
        }
      },
      render: function render(h) {
        return h('tr', {
          class: this.trClasses,
          attrs: this.trAttrs,
          // Pass native listeners to child
          on: this.$listeners
        }, this.normalizeSlot('default'));
      }
    });
  
    var digitsRx = /^\d+$/; // Parse a rowspan or colspan into a digit (or null if < 1 or NaN)
  
    var parseSpan = function parseSpan(val) {
      val = parseInt(val, 10);
      return digitsRx.test(String(val)) && val > 0 ? val : null;
    };
    /* istanbul ignore next */
  
  
    var spanValidator = function spanValidator(val) {
      return isUndefinedOrNull(val) || parseSpan(val) > 0;
    };
  
    var props$W = {
      variant: {
        type: String,
        default: null
      },
      colspan: {
        type: [Number, String],
        default: null,
        validator: spanValidator
      },
      rowspan: {
        type: [Number, String],
        default: null,
        validator: spanValidator
      },
      stackedHeading: {
        type: String,
        default: null
      },
      stickyColumn: {
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BTd = /*#__PURE__*/Vue.extend({
      name: 'BTableCell',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      inject: {
        bvTableTr: {
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: props$W,
      computed: {
        tag: function tag() {
          // Overridden by <b-th>
          return 'td';
        },
        inTbody: function inTbody() {
          return this.bvTableTr.inTbody;
        },
        inThead: function inThead() {
          return this.bvTableTr.inThead;
        },
        inTfoot: function inTfoot() {
          return this.bvTableTr.inTfoot;
        },
        isDark: function isDark() {
          return this.bvTableTr.isDark;
        },
        isStacked: function isStacked() {
          return this.bvTableTr.isStacked;
        },
        isStackedCell: function isStackedCell() {
          // We only support stacked-heading in tbody in stacked mode
          return this.inTbody && this.isStacked;
        },
        isResponsive: function isResponsive() {
          return this.bvTableTr.isResponsive;
        },
        isStickyHeader: function isStickyHeader() {
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          // Sticky headers only apply to cells in table `thead`
          return this.bvTableTr.isStickyHeader;
        },
        hasStickyHeader: function hasStickyHeader() {
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          return this.bvTableTr.hasStickyHeader;
        },
        isStickyColumn: function isStickyColumn() {
          // Needed to handle background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          // Sticky column cells are only available in responsive
          // mode (horizontal scrolling) or when sticky header mode
          // Applies to cells in `thead`, `tbody` and `tfoot`
          return !this.isStacked && (this.isResponsive || this.hasStickyHeader) && this.stickyColumn;
        },
        rowVariant: function rowVariant() {
          return this.bvTableTr.variant;
        },
        headVariant: function headVariant() {
          return this.bvTableTr.headVariant;
        },
        footVariant: function footVariant()
        /* istanbul ignore next: need to add in tests for footer variant */
        {
          return this.bvTableTr.footVariant;
        },
        tableVariant: function tableVariant() {
          return this.bvTableTr.tableVariant;
        },
        computedColspan: function computedColspan() {
          return parseSpan(this.colspan);
        },
        computedRowspan: function computedRowspan() {
          return parseSpan(this.rowspan);
        },
        cellClasses: function cellClasses() {
          // We use computed props here for improved performance by caching
          // the results of the string interpolation
          // TODO: need to add handling for footVariant
          var variant = this.variant;
  
          if (!variant && this.isStickyHeader && !this.headVariant || !variant && this.isStickyColumn) {
            // Needed for sticky-header mode as Bootstrap v4 table cells do
            // not inherit parent's background-color. Boo!
            variant = this.rowVariant || this.tableVariant || 'b-table-default';
          }
  
          return [variant ? "".concat(this.isDark ? 'bg' : 'table', "-").concat(variant) : null, this.isStickyColumn ? 'b-table-sticky-column' : null];
        },
        cellAttrs: function cellAttrs() {
          // We use computed props here for improved performance by caching
          // the results of the object spread (Object.assign)
          var headOrFoot = this.inThead || this.inTfoot; // Make sure col/rowspan's are > 0 or null
  
          var colspan = this.computedColspan;
          var rowspan = this.computedRowspan; // Default role and scope
  
          var role = 'cell';
          var scope = null; // Compute role and scope
          // We only add scopes with an explicit span of 1 or greater
  
          if (headOrFoot) {
            // Header or footer cells
            role = 'columnheader';
            scope = colspan > 0 ? 'colspan' : 'col';
          } else if (this.tag === 'th') {
            // th's in tbody
            role = 'rowheader';
            scope = rowspan > 0 ? 'rowgroup' : 'row';
          }
  
          return _objectSpread2({
            colspan: colspan,
            rowspan: rowspan,
            role: role,
            scope: scope
          }, this.$attrs, {
            // Add in the stacked cell label data-attribute if in
            // stacked mode (if a stacked heading label is provided)
            'data-label': this.isStackedCell && !isUndefinedOrNull(this.stackedHeading) ? toString$1(this.stackedHeading) : null
          });
        }
      },
      render: function render(h) {
        var content = [this.normalizeSlot('default')];
        return h(this.tag, {
          class: this.cellClasses,
          attrs: this.cellAttrs,
          // Transfer any native listeners
          on: this.$listeners
        }, [this.isStackedCell ? h('div', [content]) : content]);
      }
    });
  
    var BTh = /*#__PURE__*/Vue.extend({
      name: 'BTh',
      extends: BTd,
      computed: {
        tag: function tag() {
          return 'th';
        }
      }
    });
  
    var theadMixin = {
      props: {
        headVariant: {
          type: String,
          // 'light', 'dark' or `null` (or custom)
          default: function _default() {
            return getComponentConfig('BTable', 'headVariant');
          }
        },
        headRowVariant: {
          type: String,
          // Any Bootstrap theme variant (or custom)
          default: null
        },
        theadClass: {
          type: [String, Array, Object] // default: undefined
  
        },
        theadTrClass: {
          type: [String, Array, Object] // default: undefined
  
        }
      },
      methods: {
        fieldClasses: function fieldClasses(field) {
          // Header field (<th>) classes
          return [field.class ? field.class : '', field.thClass ? field.thClass : ''];
        },
        headClicked: function headClicked(evt, field, isFoot) {
          if (this.stopIfBusy && this.stopIfBusy(evt)) {
            // If table is busy (via provider) then don't propagate
            return;
          } else if (filterEvent(evt)) {
            // Clicked on a non-disabled control so ignore
            return;
          } else if (textSelectionActive(this.$el)) {
            // User is selecting text, so ignore
  
            /* istanbul ignore next: JSDOM doesn't support getSelection() */
            return;
          }
  
          evt.stopPropagation();
          evt.preventDefault();
          this.$emit('head-clicked', field.key, field, evt, isFoot);
        },
        renderThead: function renderThead() {
          var _this = this;
  
          var isFoot = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
          var h = this.$createElement;
          var fields = this.computedFields || [];
  
          if (this.isStackedAlways || fields.length === 0) {
            // In always stacked mode, we don't bother rendering the head/foot
            // Or if no field headings (empty table)
            return h();
          } // Reference to `selectAllRows` and `clearSelected()`, if table is selectable
  
  
          var selectAllRows = this.isSelectable ? this.selectAllRows : function () {};
          var clearSelected = this.isSelectable ? this.clearSelected : function () {}; // Helper function to generate a field <th> cell
  
          var makeCell = function makeCell(field, colIndex) {
            var ariaLabel = null;
  
            if (!field.label.trim() && !field.headerTitle) {
              // In case field's label and title are empty/blank
              // We need to add a hint about what the column is about for non-sighted users
  
              /* istanbul ignore next */
              ariaLabel = startCase(field.key);
            }
  
            var hasHeadClickListener = _this.hasListener('head-clicked') || _this.isSortable;
  
            var handlers = {};
  
            if (hasHeadClickListener) {
              handlers.click = function (evt) {
                _this.headClicked(evt, field, isFoot);
              };
  
              handlers.keydown = function (evt) {
                var keyCode = evt.keyCode;
  
                if (keyCode === KEY_CODES.ENTER || keyCode === KEY_CODES.SPACE) {
                  _this.headClicked(evt, field, isFoot);
                }
              };
            }
  
            var sortAttrs = _this.isSortable ? _this.sortTheadThAttrs(field.key, field, isFoot) : {};
            var sortClass = _this.isSortable ? _this.sortTheadThClasses(field.key, field, isFoot) : null;
            var sortLabel = _this.isSortable ? _this.sortTheadThLabel(field.key, field, isFoot) : null;
            var data = {
              key: field.key,
              class: [_this.fieldClasses(field), sortClass],
              props: {
                variant: field.variant,
                stickyColumn: field.stickyColumn
              },
              style: field.thStyle || {},
              attrs: _objectSpread2({
                // We only add a tabindex of 0 if there is a head-clicked listener
                tabindex: hasHeadClickListener ? '0' : null,
                abbr: field.headerAbbr || null,
                title: field.headerTitle || null,
                'aria-colindex': colIndex + 1,
                'aria-label': ariaLabel
              }, _this.getThValues(null, field.key, field.thAttr, isFoot ? 'foot' : 'head', {}), {}, sortAttrs),
              on: handlers
            }; // Handle edge case where in-document templates are used with new
            // `v-slot:name` syntax where the browser lower-cases the v-slot's
            // name (attributes become lower cased when parsed by the browser)
            // We have replaced the square bracket syntax with round brackets
            // to prevent confusion with dynamic slot names
  
            var slotNames = ["head(".concat(field.key, ")"), "head(".concat(field.key.toLowerCase(), ")"), 'head()'];
  
            if (isFoot) {
              // Footer will fallback to header slot names
              slotNames = ["foot(".concat(field.key, ")"), "foot(".concat(field.key.toLowerCase(), ")"), 'foot()'].concat(_toConsumableArray(slotNames));
            }
  
            var scope = {
              label: field.label,
              column: field.key,
              field: field,
              isFoot: isFoot,
              // Add in row select methods
              selectAllRows: selectAllRows,
              clearSelected: clearSelected
            };
            var content = _this.normalizeSlot(slotNames, scope) || (field.labelHtml ? h('div', {
              domProps: htmlOrText(field.labelHtml)
            }) : field.label);
            var srLabel = sortLabel ? h('span', {
              staticClass: 'sr-only'
            }, " (".concat(sortLabel, ")")) : null; // Return the header cell
  
            return h(BTh, data, [content, srLabel].filter(identity));
          }; // Generate the array of <th> cells
  
  
          var $cells = fields.map(makeCell).filter(identity); // Genrate the row(s)
  
          var $trs = [];
  
          if (isFoot) {
            var trProps = {
              variant: isUndefinedOrNull(this.footRowVariant) ? this.headRowVariant : this.footRowVariant
            };
            $trs.push(h(BTr, {
              class: this.tfootTrClass,
              props: trProps
            }, $cells));
          } else {
            var scope = {
              columns: fields.length,
              fields: fields,
              // Add in row select methods
              selectAllRows: selectAllRows,
              clearSelected: clearSelected
            };
            $trs.push(this.normalizeSlot('thead-top', scope) || h());
            $trs.push(h(BTr, {
              class: this.theadTrClass,
              props: {
                variant: this.headRowVariant
              }
            }, $cells));
          }
  
          return h(isFoot ? BTfoot : BThead, {
            key: isFoot ? 'bv-tfoot' : 'bv-thead',
            class: (isFoot ? this.tfootClass : this.theadClass) || null,
            props: isFoot ? {
              footVariant: this.footVariant || this.headVariant || null
            } : {
              headVariant: this.headVariant || null
            }
          }, $trs);
        }
      }
    };
  
    var tfootMixin = {
      props: {
        footClone: {
          type: Boolean,
          default: false
        },
        footVariant: {
          type: String,
          // 'dark', 'light', or `null` (or custom)
          default: function _default() {
            return getComponentConfig('BTable', 'footVariant');
          }
        },
        footRowVariant: {
          type: String,
          // Any Bootstrap theme variant (or custom). Falls back to `headRowVariant`
          default: null
        },
        tfootClass: {
          type: [String, Array, Object],
          default: null
        },
        tfootTrClass: {
          type: [String, Array, Object],
          default: null
        }
      },
      methods: {
        renderTFootCustom: function renderTFootCustom() {
          var h = this.$createElement;
  
          if (this.hasNormalizedSlot('custom-foot')) {
            return h(BTfoot, {
              key: 'bv-tfoot-custom',
              class: this.tfootClass || null,
              props: {
                footVariant: this.footVariant || this.headVariant || null
              }
            }, this.normalizeSlot('custom-foot', {
              items: this.computedItems.slice(),
              fields: this.computedFields.slice(),
              columns: this.computedFields.length
            }));
          } else {
            return h();
          }
        },
        renderTfoot: function renderTfoot() {
          // Passing true to renderThead will make it render a tfoot
          return this.footClone ? this.renderThead(true) : this.renderTFootCustom();
        }
      }
    };
  
    var props$X = {
      tbodyTransitionProps: {
        type: Object // default: undefined
  
      },
      tbodyTransitionHandlers: {
        type: Object // default: undefined
  
      }
    }; // @vue/component
  
    var BTbody = /*#__PURE__*/Vue.extend({
      name: 'BTbody',
      mixins: [normalizeSlotMixin],
      inheritAttrs: false,
      provide: function provide() {
        return {
          bvTableRowGroup: this
        };
      },
      inject: {
        bvTable: {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: props$X,
      computed: {
        isTbody: function isTbody() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return true;
        },
        isDark: function isDark() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.dark;
        },
        isStacked: function isStacked() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.isStacked;
        },
        isResponsive: function isResponsive() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.isResponsive;
        },
        isStickyHeader: function isStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Sticky headers are only supported in thead
          return false;
        },
        hasStickyHeader: function hasStickyHeader() {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          // Needed to handle header background classes, due to lack of
          // background color inheritance with Bootstrap v4 table CSS
          return !this.isStacked && this.bvTable.stickyHeader;
        },
        tableVariant: function tableVariant()
        /* istanbul ignore next: Not currently sniffed in tests */
        {
          // Sniffed by <b-tr> / <b-td> / <b-th>
          return this.bvTable.tableVariant;
        },
        isTransitionGroup: function isTransitionGroup() {
          return this.tbodyTransitionProps || this.tbodyTransitionHandlers;
        },
        tbodyAttrs: function tbodyAttrs() {
          return _objectSpread2({
            role: 'rowgroup'
          }, this.$attrs);
        },
        tbodyProps: function tbodyProps() {
          return this.tbodyTransitionProps ? _objectSpread2({}, this.tbodyTransitionProps, {
            tag: 'tbody'
          }) : {};
        }
      },
      render: function render(h) {
        var data = {
          props: this.tbodyProps,
          attrs: this.tbodyAttrs
        };
  
        if (this.isTransitionGroup) {
          // We use native listeners if a transition group
          // for any delegated events
          data.on = this.tbodyTransitionHandlers || {};
          data.nativeOn = this.$listeners || {};
        } else {
          // Otherwise we place any listeners on the tbody element
          data.on = this.$listeners || {};
        }
  
        return h(this.isTransitionGroup ? 'transition-group' : 'tbody', data, this.normalizeSlot('default'));
      }
    });
  
    var detailsSlotName = 'row-details';
    var tbodyRowMixin = {
      props: {
        tbodyTrClass: {
          type: [String, Array, Object, Function],
          default: null
        },
        tbodyTrAttr: {
          type: [Object, Function],
          default: null
        },
        detailsTdClass: {
          type: [String, Array, Object],
          default: null
        }
      },
      methods: {
        // Methods for computing classes, attributes and styles for table cells
        getTdValues: function getTdValues(item, key, tdValue, defValue) {
          var parent = this.$parent;
  
          if (tdValue) {
            var value = get(item, key, '');
  
            if (isFunction(tdValue)) {
              return tdValue(value, key, item);
            } else if (isString(tdValue) && isFunction(parent[tdValue])) {
              return parent[tdValue](value, key, item);
            }
  
            return tdValue;
          }
  
          return defValue;
        },
        getThValues: function getThValues(item, key, thValue, type, defValue) {
          var parent = this.$parent;
  
          if (thValue) {
            var value = get(item, key, '');
  
            if (isFunction(thValue)) {
              return thValue(value, key, item, type);
            } else if (isString(thValue) && isFunction(parent[thValue])) {
              return parent[thValue](value, key, item, type);
            }
  
            return thValue;
          }
  
          return defValue;
        },
        // Method to get the value for a field
        getFormattedValue: function getFormattedValue(item, field) {
          var key = field.key;
          var formatter = this.getFieldFormatter(key);
          var value = get(item, key, null);
  
          if (isFunction(formatter)) {
            value = formatter(value, key, item);
          }
  
          return isUndefinedOrNull(value) ? '' : value;
        },
        // Factory function methods
        toggleDetailsFactory: function toggleDetailsFactory(hasDetailsSlot, item) {
          var _this = this;
  
          // Returns a function to toggle a row's details slot
          return function () {
            if (hasDetailsSlot) {
              _this.$set(item, '_showDetails', !item._showDetails);
            }
          };
        },
        // Row event handlers
        rowHovered: function rowHovered(evt) {
          // `mouseenter` handler (non-bubbling)
          // `this.tbodyRowEvtStopped` from tbody mixin
          if (!this.tbodyRowEvtStopped(evt)) {
            // `this.emitTbodyRowEvent` from tbody mixin
            this.emitTbodyRowEvent('row-hovered', evt);
          }
        },
        rowUnhovered: function rowUnhovered(evt) {
          // `mouseleave` handler (non-bubbling)
          // `this.tbodyRowEvtStopped` from tbody mixin
          if (!this.tbodyRowEvtStopped(evt)) {
            // `this.emitTbodyRowEvent` from tbody mixin
            this.emitTbodyRowEvent('row-unhovered', evt);
          }
        },
        // Render helpers
        renderTbodyRowCell: function renderTbodyRowCell(field, colIndex, item, rowIndex) {
          var _this2 = this;
  
          // Renders a TD or TH for a row's field
          var h = this.$createElement;
          var hasDetailsSlot = this.hasNormalizedSlot(detailsSlotName);
          var formatted = this.getFormattedValue(item, field);
          var key = field.key;
          var stickyColumn = !this.isStacked && (this.isResponsive || this.stickyHeader) && field.stickyColumn; // We only uses the helper components for sticky columns to
          // improve performance of BTable/BTableLite by reducing the
          // total number of vue instances created during render
  
          var cellTag = stickyColumn ? field.isRowHeader ? BTh : BTd : field.isRowHeader ? 'th' : 'td';
          var cellVariant = item._cellVariants && item._cellVariants[key] ? item._cellVariants[key] : field.variant || null;
          var data = {
            // For the Vue key, we concatenate the column index and
            // field key (as field keys could be duplicated)
            // TODO: Although we do prevent duplicate field keys...
            //   So we could change this to: `row-${rowIndex}-cell-${key}`
            key: "row-".concat(rowIndex, "-cell-").concat(colIndex, "-").concat(key),
            class: [field.class ? field.class : '', this.getTdValues(item, key, field.tdClass, '')],
            props: {},
            attrs: _objectSpread2({
              'aria-colindex': String(colIndex + 1)
            }, field.isRowHeader ? this.getThValues(item, key, field.thAttr, 'row', {}) : this.getTdValues(item, key, field.tdAttr, {}))
          };
  
          if (stickyColumn) {
            // We are using the helper BTd or BTh
            data.props = {
              stackedHeading: this.isStacked ? field.label : null,
              stickyColumn: true,
              variant: cellVariant
            };
          } else {
            // Using native TD or TH element, so we need to
            // add in the attributes and variant class
            data.attrs['data-label'] = this.isStacked && !isUndefinedOrNull(field.label) ? toString$1(field.label) : null;
            data.attrs.role = field.isRowHeader ? 'rowheader' : 'cell';
            data.attrs.scope = field.isRowHeader ? 'row' : null; // Add in the variant class
  
            if (cellVariant) {
              data.class.push("".concat(this.dark ? 'bg' : 'table', "-").concat(cellVariant));
            }
          }
  
          var slotScope = {
            item: item,
            index: rowIndex,
            field: field,
            unformatted: get(item, key, ''),
            value: formatted,
            toggleDetails: this.toggleDetailsFactory(hasDetailsSlot, item),
            detailsShowing: Boolean(item._showDetails)
          }; // If table supports selectable mode, then add in the following scope
          // this.supportsSelectableRows will be undefined if mixin isn't loaded
  
          if (this.supportsSelectableRows) {
            slotScope.rowSelected = this.isRowSelected(rowIndex);
  
            slotScope.selectRow = function () {
              return _this2.selectRow(rowIndex);
            };
  
            slotScope.unselectRow = function () {
              return _this2.unselectRow(rowIndex);
            };
          } // The new `v-slot` syntax doesn't like a slot name starting with
          // a square bracket and if using in-document HTML templates, the
          // v-slot attributes are lower-cased by the browser.
          // Switched to round bracket syntax to prevent confusion with
          // dynamic slot name syntax.
          // We look for slots in this order: `cell(${key})`, `cell(${key.toLowerCase()})`, 'cell()'
          // Slot names are now cached by mixin tbody in `this.$_bodyFieldSlotNameCache`
          // Will be `null` if no slot (or fallback slot) exists
  
  
          var slotName = this.$_bodyFieldSlotNameCache[key];
          var $childNodes = slotName ? this.normalizeSlot(slotName, slotScope) : toString$1(formatted);
  
          if (this.isStacked) {
            // We wrap in a DIV to ensure rendered as a single cell when visually stacked!
            $childNodes = [h('div', [$childNodes])];
          } // Render either a td or th cell
  
  
          return h(cellTag, data, [$childNodes]);
        },
        renderTbodyRow: function renderTbodyRow(item, rowIndex) {
          var _this3 = this;
  
          // Renders an item's row (or rows if details supported)
          var h = this.$createElement;
          var fields = this.computedFields;
          var tableStriped = this.striped;
          var hasDetailsSlot = this.hasNormalizedSlot(detailsSlotName);
          var rowShowDetails = item._showDetails && hasDetailsSlot;
          var hasRowClickHandler = this.$listeners['row-clicked'] || this.hasSelectableRowClick; // We can return more than one TR if rowDetails enabled
  
          var $rows = []; // Details ID needed for `aria-details` when details showing
          // We set it to `null` when not showing so that attribute
          // does not appear on the element
  
          var detailsId = rowShowDetails ? this.safeId("_details_".concat(rowIndex, "_")) : null; // For each item data field in row
  
          var $tds = fields.map(function (field, colIndex) {
            return _this3.renderTbodyRowCell(field, colIndex, item, rowIndex);
          }); // Calculate the row number in the dataset (indexed from 1)
  
          var ariaRowIndex = null;
  
          if (this.currentPage && this.perPage && this.perPage > 0) {
            ariaRowIndex = String((this.currentPage - 1) * this.perPage + rowIndex + 1);
          } // Create a unique :key to help ensure that sub components are re-rendered rather than
          // re-used, which can cause issues. If a primary key is not provided we use the rendered
          // rows index within the tbody.
          // See: https://github.com/bootstrap-vue/bootstrap-vue/issues/2410
  
  
          var primaryKey = this.primaryKey;
          var primaryKeyValue = toString$1(get(item, primaryKey)) || null;
          var rowKey = primaryKeyValue || toString$1(rowIndex); // If primary key is provided, use it to generate a unique ID on each tbody > tr
          // In the format of '{tableId}__row_{primaryKeyValue}'
  
          var rowId = primaryKeyValue ? this.safeId("_row_".concat(primaryKeyValue)) : null; // Selectable classes and attributes
  
          var selectableClasses = this.selectableRowClasses ? this.selectableRowClasses(rowIndex) : {};
          var selectableAttrs = this.selectableRowAttrs ? this.selectableRowAttrs(rowIndex) : {}; // Additional classes and attributes
  
          var userTrClasses = isFunction(this.tbodyTrClass) ? this.tbodyTrClass(item, 'row') : this.tbodyTrClass;
          var userTrAttrs = isFunction(this.tbodyTrAttr) ? this.tbodyTrAttr(item, 'row') : this.tbodyTrAttr; // Add the item row
  
          $rows.push(h(BTr, {
            key: "__b-table-row-".concat(rowKey, "__"),
            ref: 'itemRows',
            refInFor: true,
            class: [userTrClasses, selectableClasses, rowShowDetails ? 'b-table-has-details' : ''],
            props: {
              variant: item._rowVariant || null
            },
            attrs: _objectSpread2({
              id: rowId
            }, userTrAttrs, {
              // Users cannot override the following attributes
              tabindex: hasRowClickHandler ? '0' : null,
              'data-pk': primaryKeyValue || null,
              'aria-details': detailsId,
              'aria-owns': detailsId,
              'aria-rowindex': ariaRowIndex
            }, selectableAttrs),
            on: {
              // Note: These events are not A11Y friendly!
              mouseenter: this.rowHovered,
              mouseleave: this.rowUnhovered
            }
          }, $tds)); // Row Details slot
  
          if (rowShowDetails) {
            var detailsScope = {
              item: item,
              index: rowIndex,
              fields: fields,
              toggleDetails: this.toggleDetailsFactory(hasDetailsSlot, item)
            }; // If table supports selectable mode, then add in the following scope
            // this.supportsSelectableRows will be undefined if mixin isn't loaded
  
            if (this.supportsSelectableRows) {
              detailsScope.rowSelected = this.isRowSelected(rowIndex);
  
              detailsScope.selectRow = function () {
                return _this3.selectRow(rowIndex);
              };
  
              detailsScope.unselectRow = function () {
                return _this3.unselectRow(rowIndex);
              };
            } // Render the details slot in a TD
  
  
            var $details = h(BTd, {
              props: {
                colspan: fields.length
              },
              class: this.detailsTdClass
            }, [this.normalizeSlot(detailsSlotName, detailsScope)]); // Add a hidden row to keep table row striping consistent when details showing
            // Only added if the table is striped
  
            if (tableStriped) {
              $rows.push( // We don't use `BTr` here as we don't need the extra functionality
              h('tr', {
                key: "__b-table-details-stripe__".concat(rowKey),
                staticClass: 'd-none',
                attrs: {
                  'aria-hidden': 'true',
                  role: 'presentation'
                }
              }));
            } // Add the actual details row
  
  
            var userDetailsTrClasses = isFunction(this.tbodyTrClass) ? this.tbodyTrClass(item, detailsSlotName) : this.tbodyTrClass;
            var userDetailsTrAttrs = isFunction(this.tbodyTrAttr) ? this.tbodyTrAttr(item, detailsSlotName) : this.tbodyTrAttr;
            $rows.push(h(BTr, {
              key: "__b-table-details__".concat(rowKey),
              staticClass: 'b-table-details',
              class: [userDetailsTrClasses],
              props: {
                variant: item._rowVariant || null
              },
              attrs: _objectSpread2({}, userDetailsTrAttrs, {
                // Users cannot override the following attributes
                id: detailsId,
                tabindex: '-1'
              })
            }, [$details]));
          } else if (hasDetailsSlot) {
            // Only add the placeholder if a the table has a row-details slot defined (but not shown)
            $rows.push(h());
  
            if (tableStriped) {
              // Add extra placeholder if table is striped
              $rows.push(h());
            }
          } // Return the row(s)
  
  
          return $rows;
        }
      }
    };
  
    var props$Y = _objectSpread2({}, props$X, {
      tbodyClass: {
        type: [String, Array, Object] // default: undefined
  
      }
    });
  
    var tbodyMixin = {
      mixins: [tbodyRowMixin],
      props: props$Y,
      methods: {
        // Helper methods
        getTbodyTrs: function getTbodyTrs() {
          // Returns all the item TR elements (excludes detail and spacer rows)
          // `this.$refs.itemRows` is an array of item TR components/elements
          // Rows should all be B-TR components, but we map to TR elements
          // Also note that `this.$refs.itemRows` may not always be in document order
          var refs = this.$refs || {};
          var tbody = refs.tbody ? refs.tbody.$el || refs.tbody : null;
          var trs = (refs.itemRows || []).map(function (tr) {
            return tr.$el || tr;
          });
          return tbody && tbody.children && tbody.children.length > 0 && trs && trs.length > 0 ? from(tbody.children).filter(function (tr) {
            return arrayIncludes(trs, tr);
          }) : [];
        },
        getTbodyTrIndex: function getTbodyTrIndex(el) {
          // Returns index of a particular TBODY item TR
          // We set `true` on closest to include self in result
  
          /* istanbul ignore next: should not normally happen */
          if (!isElement(el)) {
            return -1;
          }
  
          var tr = el.tagName === 'TR' ? el : closest('tr', el, true);
          return tr ? this.getTbodyTrs().indexOf(tr) : -1;
        },
        emitTbodyRowEvent: function emitTbodyRowEvent(type, evt) {
          // Emits a row event, with the item object, row index and original event
          if (type && this.hasListener(type) && evt && evt.target) {
            var rowIndex = this.getTbodyTrIndex(evt.target);
  
            if (rowIndex > -1) {
              // The array of TRs correlate to the `computedItems` array
              var item = this.computedItems[rowIndex];
              this.$emit(type, item, rowIndex, evt);
            }
          }
        },
        tbodyRowEvtStopped: function tbodyRowEvtStopped(evt) {
          return this.stopIfBusy && this.stopIfBusy(evt);
        },
        // Delegated row event handlers
        onTbodyRowKeydown: function onTbodyRowKeydown(evt) {
          // Keyboard navigation and row click emulation
          var target = evt.target;
  
          if (this.tbodyRowEvtStopped(evt) || target.tagName !== 'TR' || target !== document.activeElement || target.tabIndex !== 0) {
            // Early exit if not an item row TR
            return;
          }
  
          var keyCode = evt.keyCode;
  
          if (arrayIncludes([KEY_CODES.ENTER, KEY_CODES.SPACE], keyCode)) {
            // Emulated click for keyboard users, transfer to click handler
            evt.stopPropagation();
            evt.preventDefault();
            this.onTBodyRowClicked(evt);
          } else if (arrayIncludes([KEY_CODES.UP, KEY_CODES.DOWN, KEY_CODES.HOME, KEY_CODES.END], keyCode)) {
            // Keyboard navigation
            var rowIndex = this.getTbodyTrIndex(target);
  
            if (rowIndex > -1) {
              evt.stopPropagation();
              evt.preventDefault();
              var trs = this.getTbodyTrs();
              var shift = evt.shiftKey;
  
              if (keyCode === KEY_CODES.HOME || shift && keyCode === KEY_CODES.UP) {
                // Focus first row
                trs[0].focus();
              } else if (keyCode === KEY_CODES.END || shift && keyCode === KEY_CODES.DOWN) {
                // Focus last row
                trs[trs.length - 1].focus();
              } else if (keyCode === KEY_CODES.UP && rowIndex > 0) {
                // Focus previous row
                trs[rowIndex - 1].focus();
              } else if (keyCode === KEY_CODES.DOWN && rowIndex < trs.length - 1) {
                // Focus next row
                trs[rowIndex + 1].focus();
              }
            }
          }
        },
        onTBodyRowClicked: function onTBodyRowClicked(evt) {
          if (this.tbodyRowEvtStopped(evt)) {
            // If table is busy, then don't propagate
            return;
          } else if (filterEvent(evt) || textSelectionActive(this.$el)) {
            // Clicked on a non-disabled control so ignore
            // Or user is selecting text, so ignore
            return;
          }
  
          this.emitTbodyRowEvent('row-clicked', evt);
        },
        onTbodyRowMiddleMouseRowClicked: function onTbodyRowMiddleMouseRowClicked(evt) {
          if (!this.tbodyRowEvtStopped(evt) && evt.which === 2) {
            this.emitTbodyRowEvent('row-middle-clicked', evt);
          }
        },
        onTbodyRowContextmenu: function onTbodyRowContextmenu(evt) {
          if (!this.tbodyRowEvtStopped(evt)) {
            this.emitTbodyRowEvent('row-contextmenu', evt);
          }
        },
        onTbodyRowDblClicked: function onTbodyRowDblClicked(evt) {
          if (!this.tbodyRowEvtStopped(evt) && !filterEvent(evt)) {
            this.emitTbodyRowEvent('row-dblclicked', evt);
          }
        },
        // Note: Row hover handlers are handled by the tbody-row mixin
        // As mouseenter/mouseleave events do not bubble
        //
        // Render Helper
        renderTbody: function renderTbody() {
          var _this = this;
  
          // Render the tbody element and children
          var items = this.computedItems; // Shortcut to `createElement` (could use `this._c()` instead)
  
          var h = this.$createElement;
          var hasRowClickHandler = this.hasListener('row-clicked') || this.hasSelectableRowClick; // Prepare the tbody rows
  
          var $rows = []; // Add the item data rows or the busy slot
  
          var $busy = this.renderBusy ? this.renderBusy() : null;
  
          if ($busy) {
            // If table is busy and a busy slot, then return only the busy "row" indicator
            $rows.push($busy);
          } else {
            // Table isn't busy, or we don't have a busy slot
            // Create a slot cache for improved performance when looking up cell slot names
            // Values will be keyed by the field's `key` and will store the slot's name
            // Slots could be dynamic (i.e. `v-if`), so we must compute on each render
            // Used by tbody-row mixin render helper
            var cache = {};
            var defaultSlotName = this.hasNormalizedSlot('cell()') ? 'cell()' : null;
            this.computedFields.forEach(function (field) {
              var key = field.key;
              var fullName = "cell(".concat(key, ")");
              var lowerName = "cell(".concat(key.toLowerCase(), ")");
              cache[key] = _this.hasNormalizedSlot(fullName) ? fullName : _this.hasNormalizedSlot(lowerName) ? lowerName : defaultSlotName;
            }); // Created as a non-reactive property so to not trigger component updates
            // Must be a fresh object each render
  
            this.$_bodyFieldSlotNameCache = cache; // Add static top row slot (hidden in visibly stacked mode
            // as we can't control `data-label` attr)
  
            $rows.push(this.renderTopRow ? this.renderTopRow() : h()); // Render the rows
  
            items.forEach(function (item, rowIndex) {
              // Render the individual item row (rows if details slot)
              $rows.push(_this.renderTbodyRow(item, rowIndex));
            }); // Empty items / empty filtered row slot (only shows if `items.length < 1`)
  
            $rows.push(this.renderEmpty ? this.renderEmpty() : h()); // Static bottom row slot (hidden in visibly stacked mode
            // as we can't control `data-label` attr)
  
            $rows.push(this.renderBottomRow ? this.renderBottomRow() : h());
          } // Note: these events will only emit if a listener is registered
  
  
          var handlers = {
            auxclick: this.onTbodyRowMiddleMouseRowClicked,
            // TODO:
            //   Perhaps we do want to automatically prevent the
            //   default context menu from showing if there is a
            //   `row-contextmenu` listener registered
            contextmenu: this.onTbodyRowContextmenu,
            // The following event(s) is not considered A11Y friendly
            dblclick: this.onTbodyRowDblClicked // Hover events (`mouseenter`/`mouseleave`) are handled by `tbody-row` mixin
  
          }; // Add in click/keydown listeners if needed
  
          if (hasRowClickHandler) {
            handlers.click = this.onTBodyRowClicked;
            handlers.keydown = this.onTbodyRowKeydown;
          } // Assemble rows into the tbody
  
  
          var $tbody = h(BTbody, {
            ref: 'tbody',
            class: this.tbodyClass || null,
            props: {
              tbodyTransitionProps: this.tbodyTransitionProps,
              tbodyTransitionHandlers: this.tbodyTransitionHandlers
            },
            // BTbody transfers all native event listeners to the root element
            // TODO: Only set the handlers if the table is not busy
            on: handlers
          }, $rows); // Return the assembled tbody
  
          return $tbody;
        }
      }
    };
  
    var emptyMixin = {
      props: {
        showEmpty: {
          type: Boolean,
          default: false
        },
        emptyText: {
          type: String,
          default: 'There are no records to show'
        },
        emptyHtml: {
          type: String
        },
        emptyFilteredText: {
          type: String,
          default: 'There are no records matching your request'
        },
        emptyFilteredHtml: {
          type: String
        }
      },
      methods: {
        renderEmpty: function renderEmpty() {
          var h = this.$createElement;
          var items = this.computedItems;
          var $empty;
  
          if (this.showEmpty && (!items || items.length === 0) && !(this.computedBusy && this.hasNormalizedSlot('table-busy'))) {
            $empty = this.normalizeSlot(this.isFiltered ? 'emptyfiltered' : 'empty', {
              emptyFilteredHtml: this.emptyFilteredHtml,
              emptyFilteredText: this.emptyFilteredText,
              emptyHtml: this.emptyHtml,
              emptyText: this.emptyText,
              fields: this.computedFields,
              // Not sure why this is included, as it will always be an empty array
              items: this.computedItems
            });
  
            if (!$empty) {
              $empty = h('div', {
                class: ['text-center', 'my-2'],
                domProps: this.isFiltered ? htmlOrText(this.emptyFilteredHtml, this.emptyFilteredText) : htmlOrText(this.emptyHtml, this.emptyText)
              });
            }
  
            $empty = h(BTd, {
              props: {
                colspan: this.computedFields.length || null
              }
            }, [h('div', {
              attrs: {
                role: 'alert',
                'aria-live': 'polite'
              }
            }, [$empty])]);
            $empty = h(BTr, {
              key: this.isFiltered ? 'b-empty-filtered-row' : 'b-empty-row',
              staticClass: 'b-table-empty-row',
              class: [isFunction(this.tbodyTrClass) ? this.tbodyTrClass(null, 'row-empty') : this.tbodyTrClass],
              attrs: isFunction(this.tbodyTrAttr) ? this.tbodyTrAttr(null, 'row-empty') : this.tbodyTrAttr
            }, [$empty]);
          }
  
          return $empty || h();
        }
      }
    };
  
    var slotName = 'top-row';
    var topRowMixin = {
      methods: {
        renderTopRow: function renderTopRow() {
          var h = this.$createElement; // Add static Top Row slot (hidden in visibly stacked mode as we can't control the data-label)
          // If in *always* stacked mode, we don't bother rendering the row
  
          if (!this.hasNormalizedSlot(slotName) || this.stacked === true || this.stacked === '') {
            return h();
          }
  
          var fields = this.computedFields;
          return h(BTr, {
            key: 'b-top-row',
            staticClass: 'b-table-top-row',
            class: [isFunction(this.tbodyTrClass) ? this.tbodyTrClass(null, 'row-top') : this.tbodyTrClass],
            attrs: isFunction(this.tbodyTrAttr) ? this.tbodyTrAttr(null, 'row-top') : this.tbodyTrAttr
          }, [this.normalizeSlot(slotName, {
            columns: fields.length,
            fields: fields
          })]);
        }
      }
    };
  
    var slotName$1 = 'bottom-row';
    var bottomRowMixin = {
      methods: {
        renderBottomRow: function renderBottomRow() {
          var h = this.$createElement; // Static bottom row slot (hidden in visibly stacked mode as we can't control the data-label)
          // If in *always* stacked mode, we don't bother rendering the row
  
          if (!this.hasNormalizedSlot(slotName$1) || this.stacked === true || this.stacked === '') {
            return h();
          }
  
          var fields = this.computedFields;
          return h(BTr, {
            key: 'b-bottom-row',
            staticClass: 'b-table-bottom-row',
            class: [isFunction(this.tbodyTrClass) ? this.tbodyTrClass(null, 'row-bottom') : this.tbodyTrClass],
            attrs: isFunction(this.tbodyTrAttr) ? this.tbodyTrAttr(null, 'row-bottom') : this.tbodyTrAttr
          }, this.normalizeSlot(slotName$1, {
            columns: fields.length,
            fields: fields
          }));
        }
      }
    };
  
    var busySlotName = 'table-busy';
    var busyMixin = {
      props: {
        busy: {
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          localBusy: false
        };
      },
      computed: {
        computedBusy: function computedBusy() {
          return this.busy || this.localBusy;
        }
      },
      watch: {
        localBusy: function localBusy(newVal, oldVal) {
          if (newVal !== oldVal) {
            this.$emit('update:busy', newVal);
          }
        }
      },
      methods: {
        // Event handler helper
        stopIfBusy: function stopIfBusy(evt) {
          if (this.computedBusy) {
            // If table is busy (via provider) then don't propagate
            evt.preventDefault();
            evt.stopPropagation();
            return true;
          }
  
          return false;
        },
        // Render the busy indicator or return `null` if not busy
        renderBusy: function renderBusy() {
          var h = this.$createElement; // Return a busy indicator row, or `null` if not busy
  
          if (this.computedBusy && this.hasNormalizedSlot(busySlotName)) {
            // Show the busy slot
            return h(BTr, {
              key: 'table-busy-slot',
              staticClass: 'b-table-busy-slot',
              class: [isFunction(this.tbodyTrClass) ? this.tbodyTrClass(null, busySlotName) : this.tbodyTrClass],
              attrs: isFunction(this.tbodyTrAttr) ? this.tbodyTrAttr(null, busySlotName) : this.tbodyTrAttr
            }, [h(BTd, {
              props: {
                colspan: this.computedFields.length || null
              }
            }, [this.normalizeSlot(busySlotName)])]);
          } else {
            // We return `null` here so that we can determine if we need to
            // render the table items rows or not
            return null;
          }
        }
      }
    };
  
    var selectableMixin = {
      props: {
        selectable: {
          type: Boolean,
          default: false
        },
        selectMode: {
          type: String,
          default: 'multi',
          validator: function validator(val) {
            return arrayIncludes(['range', 'multi', 'single'], val);
          }
        },
        selectedVariant: {
          type: String,
          default: function _default() {
            return getComponentConfig('BTable', 'selectedVariant');
          }
        },
        noSelectOnClick: {
          // Disable use of click handlers for row selection
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          selectedRows: [],
          selectedLastRow: -1
        };
      },
      computed: {
        isSelectable: function isSelectable() {
          return this.selectable && this.selectMode;
        },
        hasSelectableRowClick: function hasSelectableRowClick() {
          return this.isSelectable && !this.noSelectOnClick;
        },
        supportsSelectableRows: function supportsSelectableRows() {
          return true;
        },
        selectableHasSelection: function selectableHasSelection() {
          return this.isSelectable && this.selectedRows && this.selectedRows.length > 0 && this.selectedRows.some(identity);
        },
        selectableIsMultiSelect: function selectableIsMultiSelect() {
          return this.isSelectable && arrayIncludes(['range', 'multi'], this.selectMode);
        },
        selectableTableClasses: function selectableTableClasses() {
          var _ref;
  
          return _ref = {
            'b-table-selectable': this.isSelectable
          }, _defineProperty(_ref, "b-table-select-".concat(this.selectMode), this.isSelectable), _defineProperty(_ref, 'b-table-selecting', this.selectableHasSelection), _defineProperty(_ref, 'b-table-selectable-no-click', this.isSelectable && !this.hasSelectableRowClick), _ref;
        },
        selectableTableAttrs: function selectableTableAttrs() {
          return {
            // TODO:
            //   Should this attribute not be included when no-select-on-click is set
            //   since this attribute implies keyboard navigation?
            'aria-multiselectable': !this.isSelectable ? null : this.selectableIsMultiSelect ? 'true' : 'false'
          };
        }
      },
      watch: {
        computedItems: function computedItems(newVal, oldVal) {
          // Reset for selectable
          var equal = false;
  
          if (this.isSelectable && this.selectedRows.length > 0) {
            // Quick check against array length
            equal = isArray(newVal) && isArray(oldVal) && newVal.length === oldVal.length;
  
            for (var i = 0; equal && i < newVal.length; i++) {
              // Look for the first non-loosely equal row, after ignoring reserved fields
              equal = looseEqual(sanitizeRow(newVal[i]), sanitizeRow(oldVal[i]));
            }
          }
  
          if (!equal) {
            this.clearSelected();
          }
        },
        selectable: function selectable(newVal) {
          this.clearSelected();
          this.setSelectionHandlers(newVal);
        },
        selectMode: function selectMode() {
          this.clearSelected();
        },
        hasSelectableRowClick: function hasSelectableRowClick(newVal) {
          this.clearSelected();
          this.setSelectionHandlers(!newVal);
        },
        selectedRows: function selectedRows(_selectedRows, oldVal) {
          var _this = this;
  
          if (this.isSelectable && !looseEqual(_selectedRows, oldVal)) {
            var items = []; // `.forEach()` skips over non-existent indices (on sparse arrays)
  
            _selectedRows.forEach(function (v, idx) {
              if (v) {
                items.push(_this.computedItems[idx]);
              }
            });
  
            this.$emit('row-selected', items);
          }
        }
      },
      beforeMount: function beforeMount() {
        // Set up handlers if needed
        if (this.isSelectable) {
          this.setSelectionHandlers(true);
        }
      },
      methods: {
        // Public methods
        selectRow: function selectRow(index) {
          // Select a particular row (indexed based on computedItems)
          if (this.isSelectable && isNumber(index) && index >= 0 && index < this.computedItems.length && !this.isRowSelected(index)) {
            var selectedRows = this.selectableIsMultiSelect ? this.selectedRows.slice() : [];
            selectedRows[index] = true;
            this.selectedLastClicked = -1;
            this.selectedRows = selectedRows;
          }
        },
        unselectRow: function unselectRow(index) {
          // Un-select a particular row (indexed based on `computedItems`)
          if (this.isSelectable && isNumber(index) && this.isRowSelected(index)) {
            var selectedRows = this.selectedRows.slice();
            selectedRows[index] = false;
            this.selectedLastClicked = -1;
            this.selectedRows = selectedRows;
          }
        },
        selectAllRows: function selectAllRows() {
          var length = this.computedItems.length;
  
          if (this.isSelectable && length > 0) {
            this.selectedLastClicked = -1;
            this.selectedRows = this.selectableIsMultiSelect ? range(length).map(function () {
              return true;
            }) : [true];
          }
        },
        isRowSelected: function isRowSelected(index) {
          // Determine if a row is selected (indexed based on `computedItems`)
          return !!(isNumber(index) && this.selectedRows[index]);
        },
        clearSelected: function clearSelected() {
          // Clear any active selected row(s)
          this.selectedLastClicked = -1;
          this.selectedRows = [];
        },
        // Internal private methods
        selectableRowClasses: function selectableRowClasses(index) {
          if (this.isSelectable && this.isRowSelected(index)) {
            var variant = this.selectedVariant;
            return _defineProperty({
              'b-table-row-selected': true
            }, "".concat(this.dark ? 'bg' : 'table', "-").concat(variant), variant);
          } else {
            return {};
          }
        },
        selectableRowAttrs: function selectableRowAttrs(index) {
          return {
            'aria-selected': !this.isSelectable ? null : this.isRowSelected(index) ? 'true' : 'false'
          };
        },
        setSelectionHandlers: function setSelectionHandlers(on) {
          var method = on && !this.noSelectOnClick ? '$on' : '$off'; // Handle row-clicked event
  
          this[method]('row-clicked', this.selectionHandler); // Clear selection on filter, pagination, and sort changes
  
          this[method]('filtered', this.clearSelected);
          this[method]('context-changed', this.clearSelected);
        },
        selectionHandler: function selectionHandler(item, index, evt) {
          /* istanbul ignore if: should never happen */
          if (!this.isSelectable || this.noSelectOnClick) {
            // Don't do anything if table is not in selectable mode
            this.clearSelected();
            return;
          }
  
          var selectMode = this.selectMode;
          var selectedRows = this.selectedRows.slice();
          var selected = !selectedRows[index]; // Note 'multi' mode needs no special event handling
  
          if (selectMode === 'single') {
            selectedRows = [];
          } else if (selectMode === 'range') {
            if (this.selectedLastRow > -1 && evt.shiftKey) {
              // range
              for (var idx = Math.min(this.selectedLastRow, index); idx <= Math.max(this.selectedLastRow, index); idx++) {
                selectedRows[idx] = true;
              }
  
              selected = true;
            } else {
              if (!(evt.ctrlKey || evt.metaKey)) {
                // Clear range selection if any
                selectedRows = [];
                selected = true;
              }
  
              this.selectedLastRow = selected ? index : -1;
            }
          }
  
          selectedRows[index] = selected;
          this.selectedRows = selectedRows;
        }
      }
    };
  
    var providerMixin = {
      mixins: [listenOnRootMixin],
      props: {
        // Prop override(s)
        items: {
          // Adds in 'Function' support
          type: [Array, Function],
          default: function _default()
          /* istanbul ignore next */
          {
            return [];
          }
        },
        // Additional props
        noProviderPaging: {
          type: Boolean,
          default: false
        },
        noProviderSorting: {
          type: Boolean,
          default: false
        },
        noProviderFiltering: {
          type: Boolean,
          default: false
        },
        apiUrl: {
          // Passthrough prop. Passed to the context object. Not used by b-table directly
          type: String,
          default: ''
        }
      },
      computed: {
        hasProvider: function hasProvider() {
          return isFunction(this.items);
        },
        providerTriggerContext: function providerTriggerContext() {
          // Used to trigger the provider function via a watcher. Only the fields that
          // are needed for triggering a provider update are included. Note that the
          // regular this.context is sent to the provider during fetches though, as they
          // may need all the prop info.
          var ctx = {
            apiUrl: this.apiUrl,
            filter: null,
            sortBy: null,
            sortDesc: null,
            perPage: null,
            currentPage: null
          };
  
          if (!this.noProviderFiltering) {
            // Either a string, or could be an object or array.
            ctx.filter = this.localFilter;
          }
  
          if (!this.noProviderSorting) {
            ctx.sortBy = this.localSortBy;
            ctx.sortDesc = this.localSortDesc;
          }
  
          if (!this.noProviderPaging) {
            ctx.perPage = this.perPage;
            ctx.currentPage = this.currentPage;
          }
  
          return clone(ctx);
        }
      },
      watch: {
        // Provider update triggering
        items: function items(newVal) {
          // If a new provider has been specified, trigger an update
          if (this.hasProvider || isFunction(newVal)) {
            this.$nextTick(this._providerUpdate);
          }
        },
        providerTriggerContext: function providerTriggerContext(newVal, oldVal) {
          // Trigger the provider to update as the relevant context values have changed.
          if (!looseEqual(newVal, oldVal)) {
            this.$nextTick(this._providerUpdate);
          }
        }
      },
      mounted: function mounted() {
        var _this = this;
  
        // Call the items provider if necessary
        if (this.hasProvider && (!this.localItems || this.localItems.length === 0)) {
          // Fetch on mount if localItems is empty
          this._providerUpdate();
        } // Listen for global messages to tell us to force refresh the table
  
  
        this.listenOnRoot('bv::refresh::table', function (id) {
          if (id === _this.id || id === _this) {
            _this.refresh();
          }
        });
      },
      methods: {
        refresh: function refresh() {
          // Public Method: Force a refresh of the provider function
          this.$off('refreshed', this.refresh);
  
          if (this.computedBusy) {
            // Can't force an update when forced busy by user (busy prop === true)
            if (this.localBusy && this.hasProvider) {
              // But if provider running (localBusy), re-schedule refresh once `refreshed` emitted
              this.$on('refreshed', this.refresh);
            }
          } else {
            this.clearSelected();
  
            if (this.hasProvider) {
              this.$nextTick(this._providerUpdate);
            } else {
              /* istanbul ignore next */
              this.localItems = isArray(this.items) ? this.items.slice() : [];
            }
          }
        },
        // Provider related methods
        _providerSetLocal: function _providerSetLocal(items) {
          this.localItems = isArray(items) ? items.slice() : [];
          this.localBusy = false;
          this.$emit('refreshed'); // New root emit
  
          if (this.id) {
            this.emitOnRoot('bv::table::refreshed', this.id);
          }
        },
        _providerUpdate: function _providerUpdate() {
          var _this2 = this;
  
          // Refresh the provider function items.
          if (!this.hasProvider) {
            // Do nothing if no provider
            return;
          } // If table is busy, wait until refreshed before calling again
  
  
          if (this.computedBusy) {
            // Schedule a new refresh once `refreshed` is emitted
            this.$nextTick(this.refresh);
            return;
          } // Set internal busy state
  
  
          this.localBusy = true; // Call provider function with context and optional callback after DOM is fully updated
  
          this.$nextTick(function () {
            try {
              // Call provider function passing it the context and optional callback
              var data = _this2.items(_this2.context, _this2._providerSetLocal);
  
              if (isPromise(data)) {
                // Provider returned Promise
                data.then(function (items) {
                  // Provider resolved with items
                  _this2._providerSetLocal(items);
                });
              } else if (isArray(data)) {
                // Provider returned Array data
                _this2._providerSetLocal(data);
              } else {
                /* istanbul ignore if */
                if (_this2.items.length !== 2) {
                  // Check number of arguments provider function requested
                  // Provider not using callback (didn't request second argument), so we clear
                  // busy state as most likely there was an error in the provider function
  
                  /* istanbul ignore next */
                  warn("Provider function didn't request callback and did not return a promise or data.", 'BTable');
                  _this2.localBusy = false;
                }
              }
            } catch (e)
            /* istanbul ignore next */
            {
              // Provider function borked on us, so we spew out a warning
              // and clear the busy state
              warn("Provider function error [".concat(e.name, "] ").concat(e.message, "."), 'BTable');
              _this2.localBusy = false;
  
              _this2.$off('refreshed', _this2.refresh);
            }
          });
        }
      }
    };
  
    // Includes all main table styling options
  
    var tableRendererMixin = {
      // Don't place attributes on root element automatically,
      // as table could be wrapped in responsive `<div>`
      inheritAttrs: false,
      provide: function provide() {
        return {
          bvTable: this
        };
      },
      props: {
        striped: {
          type: Boolean,
          default: false
        },
        bordered: {
          type: Boolean,
          default: false
        },
        borderless: {
          type: Boolean,
          default: false
        },
        outlined: {
          type: Boolean,
          default: false
        },
        dark: {
          type: Boolean,
          default: false
        },
        hover: {
          type: Boolean,
          default: false
        },
        small: {
          type: Boolean,
          default: false
        },
        fixed: {
          type: Boolean,
          default: false
        },
        responsive: {
          type: [Boolean, String],
          default: false
        },
        stickyHeader: {
          // If a string, it is assumed to be the table `max-height` value
          type: [Boolean, String],
          default: false
        },
        noBorderCollapse: {
          type: Boolean,
          default: false
        },
        captionTop: {
          type: Boolean,
          default: false
        },
        tableVariant: {
          type: String,
          default: null
        },
        tableClass: {
          type: [String, Array, Object],
          default: null
        }
      },
      computed: {
        // Layout related computed props
        isResponsive: function isResponsive() {
          var responsive = this.responsive === '' ? true : this.responsive;
          return this.isStacked ? false : responsive;
        },
        isStickyHeader: function isStickyHeader() {
          var stickyHeader = this.stickyHeader === '' ? true : this.stickyHeader;
          return this.isStacked ? false : stickyHeader;
        },
        wrapperClasses: function wrapperClasses() {
          return [this.isStickyHeader ? 'b-table-sticky-header' : '', this.isResponsive === true ? 'table-responsive' : this.isResponsive ? "table-responsive-".concat(this.responsive) : ''].filter(identity);
        },
        wrapperStyles: function wrapperStyles() {
          return this.isStickyHeader && !isBoolean(this.isStickyHeader) ? {
            maxHeight: this.isStickyHeader
          } : {};
        },
        tableClasses: function tableClasses() {
          var hover = this.isTableSimple ? this.hover : this.hover && this.computedItems.length > 0 && !this.computedBusy;
          return [// User supplied classes
          this.tableClass, // Styling classes
          {
            'table-striped': this.striped,
            'table-hover': hover,
            'table-dark': this.dark,
            'table-bordered': this.bordered,
            'table-borderless': this.borderless,
            'table-sm': this.small,
            // The following are b-table custom styles
            border: this.outlined,
            'b-table-fixed': this.fixed,
            'b-table-caption-top': this.captionTop,
            'b-table-no-border-collapse': this.noBorderCollapse
          }, this.tableVariant ? "".concat(this.dark ? 'bg' : 'table', "-").concat(this.tableVariant) : '', // Stacked table classes
          this.stackedTableClasses, // Selectable classes
          this.selectableTableClasses];
        },
        tableAttrs: function tableAttrs() {
          // Preserve user supplied aria-describedby, if provided in `$attrs`
          var adb = [(this.$attrs || {})['aria-describedby'], this.captionId].filter(identity).join(' ') || null;
          var items = this.computedItems;
          var filteredItems = this.filteredItems;
          var fields = this.computedFields;
          var selectableAttrs = this.selectableTableAttrs || {};
          var ariaAttrs = this.isTableSimple ? {} : {
            'aria-busy': this.computedBusy ? 'true' : 'false',
            'aria-colcount': toString$1(fields.length),
            'aria-describedby': adb
          };
          var rowCount = items && filteredItems && filteredItems.length > items.length ? toString$1(filteredItems.length) : null;
          return _objectSpread2({
            // We set `aria-rowcount` before merging in `$attrs`,
            // in case user has supplied their own
            'aria-rowcount': rowCount
          }, this.$attrs, {
            // Now we can override any `$attrs` here
            id: this.safeId(),
            role: 'table'
          }, ariaAttrs, {}, selectableAttrs);
        }
      },
      render: function render(h) {
        var $content = [];
  
        if (this.isTableSimple) {
          $content.push(this.normalizeSlot('default'));
        } else {
          // Build the `<caption>` (from caption mixin)
          $content.push(this.renderCaption ? this.renderCaption() : null); // Build the `<colgroup>`
  
          $content.push(this.renderColgroup ? this.renderColgroup() : null); // Build the `<thead>`
  
          $content.push(this.renderThead ? this.renderThead() : null); // Build the `<tbody>`
  
          $content.push(this.renderTbody ? this.renderTbody() : null); // Build the `<tfoot>`
  
          $content.push(this.renderTfoot ? this.renderTfoot() : null);
        } // Assemble `<table>`
  
  
        var $table = h('table', {
          key: 'b-table',
          staticClass: 'table b-table',
          class: this.tableClasses,
          attrs: this.tableAttrs
        }, $content.filter(identity)); // Add responsive/sticky wrapper if needed and return table
  
        return this.wrapperClasses.length > 0 ? h('div', {
          key: 'wrap',
          class: this.wrapperClasses,
          style: this.wrapperStyles
        }, [$table]) : $table;
      }
    };
  
    // @vue/component
  
    var BTable = /*#__PURE__*/Vue.extend({
      name: 'BTable',
      // Order of mixins is important!
      // They are merged from first to last, followed by this component.
      mixins: [// Required Mixins
      hasListenerMixin, idMixin, normalizeSlotMixin, itemsMixin, tableRendererMixin, stackedMixin, theadMixin, tfootMixin, tbodyMixin, // Features Mixins
      stackedMixin, filteringMixin, sortingMixin, paginationMixin$1, captionMixin, colgroupMixin, selectableMixin, emptyMixin, topRowMixin, bottomRowMixin, busyMixin, providerMixin] // render function provided by table-renderer mixin
  
    });
  
    // @vue/component
  
    var BTableLite = /*#__PURE__*/Vue.extend({
      name: 'BTableLite',
      // Order of mixins is important!
      // They are merged from first to last, followed by this component.
      mixins: [// Required mixins
      hasListenerMixin, idMixin, normalizeSlotMixin, itemsMixin, tableRendererMixin, stackedMixin, theadMixin, tfootMixin, tbodyMixin, // Features Mixins
      // These are pretty lightweight, and are useful for lightweight tables
      captionMixin, colgroupMixin] // render function provided by table-renderer mixin
  
    });
  
    // @vue/component
  
    var BTableSimple = /*#__PURE__*/Vue.extend({
      name: 'BTableSimple',
      // Order of mixins is important!
      // They are merged from first to last, followed by this component.
      mixins: [// Required mixins
      idMixin, normalizeSlotMixin, tableRendererMixin, // feature mixin
      // Stacked requires extra handling by users via
      // the table cell `stacked-heading` prop
      stackedMixin],
      computed: {
        isTableSimple: function isTableSimple() {
          return true;
        }
      } // render function provided by table-renderer mixin
  
    });
  
    var TableLitePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BTableLite: BTableLite
      }
    });
    var TableSimplePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BTableSimple: BTableSimple,
        BTbody: BTbody,
        BThead: BThead,
        BTfoot: BTfoot,
        BTr: BTr,
        BTd: BTd,
        BTh: BTh
      }
    });
    var TablePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BTable: BTable
      },
      plugins: {
        TableLitePlugin: TableLitePlugin,
        TableSimplePlugin: TableSimplePlugin
      }
    });
  
    var navProps = omit(props$I, ['tabs', 'isNavBar', 'cardHeader']); // -- Utils --
    // Filter function to filter out disabled tabs
  
    var notDisabled = function notDisabled(tab) {
      return !tab.disabled;
    }; // --- Helper components ---
    // @vue/component
  
  
    var BTabButtonHelper = /*#__PURE__*/Vue.extend({
      name: 'BTabButtonHelper',
      inject: {
        bvTabs: {
          default: function _default()
          /* istanbul ignore next */
          {
            return {};
          }
        }
      },
      props: {
        // Reference to the child <b-tab> instance
        tab: {
          default: null
        },
        tabs: {
          type: Array,
          default: function _default()
          /* istanbul ignore next */
          {
            return [];
          }
        },
        id: {
          type: String,
          default: null
        },
        controls: {
          type: String,
          default: null
        },
        tabIndex: {
          type: Number,
          default: null
        },
        posInSet: {
          type: Number,
          default: null
        },
        setSize: {
          type: Number,
          default: null
        },
        noKeyNav: {
          type: Boolean,
          default: false
        }
      },
      methods: {
        focus: function focus() {
          if (this.$refs && this.$refs.link && this.$refs.link.focus) {
            this.$refs.link.focus();
          }
        },
        handleEvt: function handleEvt(evt) {
          var stop = function stop() {
            evt.preventDefault();
            evt.stopPropagation();
          };
  
          if (this.tab.disabled) {
            /* istanbul ignore next */
            return;
          }
  
          var type = evt.type;
          var key = evt.keyCode;
          var shift = evt.shiftKey;
  
          if (type === 'click') {
            stop();
            this.$emit('click', evt);
          } else if (type === 'keydown' && key === KEY_CODES.SPACE) {
            // For ARIA tabs the SPACE key will also trigger a click/select
            // Even with keyboard navigation disabled, SPACE should "click" the button
            // See: https://github.com/bootstrap-vue/bootstrap-vue/issues/4323
            stop();
            this.$emit('click', evt);
          } else if (type === 'keydown' && !this.noKeyNav) {
            // For keyboard navigation
            if (key === KEY_CODES.UP || key === KEY_CODES.LEFT || key === KEY_CODES.HOME) {
              stop();
  
              if (shift || key === KEY_CODES.HOME) {
                this.$emit('first', evt);
              } else {
                this.$emit('prev', evt);
              }
            } else if (key === KEY_CODES.DOWN || key === KEY_CODES.RIGHT || key === KEY_CODES.END) {
              stop();
  
              if (shift || key === KEY_CODES.END) {
                this.$emit('last', evt);
              } else {
                this.$emit('next', evt);
              }
            }
          }
        }
      },
      render: function render(h) {
        var link = h(BLink, {
          ref: 'link',
          staticClass: 'nav-link',
          class: [{
            active: this.tab.localActive && !this.tab.disabled,
            disabled: this.tab.disabled
          }, this.tab.titleLinkClass, // Apply <b-tabs> `activeNavItemClass` styles when the tab is active
          this.tab.localActive ? this.bvTabs.activeNavItemClass : null],
          props: {
            disabled: this.tab.disabled
          },
          attrs: _objectSpread2({}, this.tab.titleLinkAttributes, {
            role: 'tab',
            id: this.id,
            // Roving tab index when keynav enabled
            tabindex: this.tabIndex,
            'aria-selected': this.tab.localActive && !this.tab.disabled ? 'true' : 'false',
            'aria-setsize': this.setSize,
            'aria-posinset': this.posInSet,
            'aria-controls': this.controls
          }),
          on: {
            click: this.handleEvt,
            keydown: this.handleEvt
          }
        }, [this.tab.normalizeSlot('title') || this.tab.title]);
        return h('li', {
          staticClass: 'nav-item',
          class: [this.tab.titleItemClass],
          attrs: {
            role: 'presentation'
          }
        }, [link]);
      }
    }); // @vue/component
  
    var BTabs = /*#__PURE__*/Vue.extend({
      name: 'BTabs',
      mixins: [idMixin, normalizeSlotMixin],
      provide: function provide() {
        return {
          bvTabs: this
        };
      },
      model: {
        prop: 'value',
        event: 'input'
      },
      props: _objectSpread2({}, navProps, {
        tag: {
          type: String,
          default: 'div'
        },
        card: {
          type: Boolean,
          default: false
        },
        end: {
          // Synonym for 'bottom'
          type: Boolean,
          default: false
        },
        noFade: {
          type: Boolean,
          default: false
        },
        noNavStyle: {
          type: Boolean,
          default: false
        },
        noKeyNav: {
          type: Boolean,
          default: false
        },
        lazy: {
          // This prop is sniffed by the <b-tab> child
          type: Boolean,
          default: false
        },
        contentClass: {
          type: [String, Array, Object],
          default: null
        },
        navClass: {
          type: [String, Array, Object],
          default: null
        },
        navWrapperClass: {
          type: [String, Array, Object],
          default: null
        },
        activeNavItemClass: {
          // Only applied to the currently active <b-nav-item>
          type: [String, Array, Object],
          default: null
        },
        activeTabClass: {
          // Only applied to the currently active <b-tab>
          // This prop is sniffed by the <b-tab> child
          type: [String, Array, Object],
          default: null
        },
        value: {
          // v-model
          type: Number,
          default: null
        }
      }),
      data: function data() {
        var tabIdx = parseInt(this.value, 10);
        tabIdx = isNaN(tabIdx) ? -1 : tabIdx;
        return {
          // Index of current tab
          currentTab: tabIdx,
          // Array of direct child <b-tab> instances, in DOM order
          tabs: [],
          // Array of child instances registered (for triggering reactive updates)
          registeredTabs: [],
          // Flag to know if we are mounted or not
          isMounted: false
        };
      },
      computed: {
        fade: function fade() {
          // This computed prop is sniffed by the tab child
          return !this.noFade;
        },
        localNavClass: function localNavClass() {
          var classes = [];
  
          if (this.card && this.vertical) {
            classes.push('card-header', 'h-100', 'border-bottom-0', 'rounded-0');
          }
  
          return [].concat(classes, [this.navClass]);
        }
      },
      watch: {
        currentTab: function currentTab(newVal) {
          var index = -1; // Ensure only one tab is active at most
  
          this.tabs.forEach(function (tab, idx) {
            if (newVal === idx && !tab.disabled) {
              tab.localActive = true;
              index = idx;
            } else {
              tab.localActive = false;
            }
          }); // Update the v-model
  
          this.$emit('input', index);
        },
        value: function value(newVal, oldVal) {
          if (newVal !== oldVal) {
            newVal = parseInt(newVal, 10);
            newVal = isNaN(newVal) ? -1 : newVal;
            oldVal = parseInt(oldVal, 10) || 0;
            var tabs = this.tabs;
  
            if (tabs[newVal] && !tabs[newVal].disabled) {
              this.activateTab(tabs[newVal]);
            } else {
              // Try next or prev tabs
              if (newVal < oldVal) {
                this.previousTab();
              } else {
                this.nextTab();
              }
            }
          }
        },
        registeredTabs: function registeredTabs() {
          var _this = this;
  
          // Each b-tab will register/unregister itself.
          // We use this to detect when tabs are added/removed
          // to trigger the update of the tabs.
          this.$nextTick(function () {
            requestAF(function () {
              _this.updateTabs();
            });
          });
        },
        tabs: function tabs(newVal, oldVal) {
          var _this2 = this;
  
          // If tabs added, removed, or re-ordered, we emit a `changed` event.
          // We use `tab._uid` instead of `tab.safeId()`, as the later is changed
          // in a nextTick if no explicit ID is provided, causing duplicate emits.
          if (!looseEqual(newVal.map(function (t) {
            return t._uid;
          }), oldVal.map(function (t) {
            return t._uid;
          }))) {
            // In a nextTick to ensure currentTab has been set first.
            this.$nextTick(function () {
              // We emit shallow copies of the new and old arrays of tabs, to
              // prevent users from potentially mutating the internal arrays.
              _this2.$emit('changed', newVal.slice(), oldVal.slice());
            });
          }
        },
        isMounted: function isMounted(newVal) {
          var _this3 = this;
  
          // Trigger an update after mounted.  Needed for tabs inside lazy modals.
          if (newVal) {
            requestAF(function () {
              _this3.updateTabs();
            });
          } // Enable or disable the observer
  
  
          this.setObserver(newVal);
        }
      },
      created: function created() {
        var _this4 = this;
  
        var tabIdx = parseInt(this.value, 10);
        this.currentTab = isNaN(tabIdx) ? -1 : tabIdx;
        this._bvObserver = null; // For SSR and to make sure only a single tab is shown on mount
        // We wrap this in a `$nextTick()` to ensure the child tabs have been created
  
        this.$nextTick(function () {
          _this4.updateTabs();
        });
      },
      mounted: function mounted() {
        var _this5 = this;
  
        // Call `updateTabs()` just in case...
        this.updateTabs();
        this.$nextTick(function () {
          // Flag we are now mounted and to switch to DOM for tab probing.
          // As this.$slots.default appears to lie about component instances
          // after b-tabs is destroyed and re-instantiated.
          // And this.$children does not respect DOM order.
          _this5.isMounted = true;
        });
      },
      deactivated: function deactivated()
      /* istanbul ignore next */
      {
        this.isMounted = false;
      },
      activated: function activated()
      /* istanbul ignore next */
      {
        var _this6 = this;
  
        var tabIdx = parseInt(this.value, 10);
        this.currentTab = isNaN(tabIdx) ? -1 : tabIdx;
        this.$nextTick(function () {
          _this6.updateTabs();
  
          _this6.isMounted = true;
        });
      },
      beforeDestroy: function beforeDestroy() {
        this.isMounted = false;
      },
      destroyed: function destroyed() {
        // Ensure no references to child instances exist
        this.tabs = [];
      },
      methods: {
        registerTab: function registerTab(tab) {
          var _this7 = this;
  
          if (!arrayIncludes(this.registeredTabs, tab)) {
            this.registeredTabs.push(tab);
            tab.$once('hook:destroyed', function () {
              _this7.unregisterTab(tab);
            });
          }
        },
        unregisterTab: function unregisterTab(tab) {
          this.registeredTabs = this.registeredTabs.slice().filter(function (t) {
            return t !== tab;
          });
        },
        setObserver: function setObserver(on) {
          // DOM observer is needed to detect changes in order of tabs
          if (on) {
            // Make sure no existing observer running
            this.setObserver(false);
            var self = this;
            /* istanbul ignore next: difficult to test mutation observer in JSDOM */
  
            var handler = function handler() {
              // We delay the update to ensure that `tab.safeId()` has
              // updated with the final ID value.
              self.$nextTick(function () {
                requestAF(function () {
                  self.updateTabs();
                });
              });
            }; // Watch for changes to <b-tab> sub components
  
  
            this._bvObserver = observeDom(this.$refs.tabsContainer, handler, {
              childList: true,
              subtree: false,
              attributes: true,
              attributeFilter: ['id']
            });
          } else {
            if (this._bvObserver && this._bvObserver.disconnect) {
              this._bvObserver.disconnect();
            }
  
            this._bvObserver = null;
          }
        },
        getTabs: function getTabs() {
          // We use registeredTabs as the source of truth for child tab components. And we
          // filter out any BTab components that are extended BTab with a root child BTab.
          // https://github.com/bootstrap-vue/bootstrap-vue/issues/3260
          var tabs = this.registeredTabs.filter(function (tab) {
            return tab.$children.filter(function (t) {
              return t._isTab;
            }).length === 0;
          }); // DOM Order of Tabs
  
          var order = [];
  
          if (this.isMounted && tabs.length > 0) {
            // We rely on the DOM when mounted to get the 'true' order of the b-tab children.
            // querySelectorAll(...) always returns elements in document order, regardless of
            // order specified in the selector.
            var selector = tabs.map(function (tab) {
              return "#".concat(tab.safeId());
            }).join(', ');
            order = selectAll(selector, this.$el).map(function (el) {
              return el.id;
            }).filter(identity);
          } // Stable sort keeps the original order if not found in the
          // `order` array, which will be an empty array before mount.
  
  
          return stableSort(tabs, function (a, b) {
            return order.indexOf(a.safeId()) - order.indexOf(b.safeId());
          });
        },
        // Update list of <b-tab> children
        updateTabs: function updateTabs() {
          // Probe tabs
          var tabs = this.getTabs(); // Find *last* active non-disabled tab in current tabs
          // We trust tab state over currentTab, in case tabs were added/removed/re-ordered
  
          var tabIndex = tabs.indexOf(tabs.slice().reverse().find(function (tab) {
            return tab.localActive && !tab.disabled;
          })); // Else try setting to currentTab
  
          if (tabIndex < 0) {
            var currentTab = this.currentTab;
  
            if (currentTab >= tabs.length) {
              // Handle last tab being removed, so find the last non-disabled tab
              tabIndex = tabs.indexOf(tabs.slice().reverse().find(notDisabled));
            } else if (tabs[currentTab] && !tabs[currentTab].disabled) {
              // Current tab is not disabled
              tabIndex = currentTab;
            }
          } // Else find *first* non-disabled tab in current tabs
  
  
          if (tabIndex < 0) {
            tabIndex = tabs.indexOf(tabs.find(notDisabled));
          } // Set the current tab state to active
  
  
          tabs.forEach(function (tab) {
            // tab.localActive = idx === tabIndex && !tab.disabled
            tab.localActive = false;
          });
  
          if (tabs[tabIndex]) {
            tabs[tabIndex].localActive = true;
          } // Update the array of tab children
  
  
          this.tabs = tabs; // Set the currentTab index (can be -1 if no non-disabled tabs)
  
          this.currentTab = tabIndex;
        },
        // Find a button that controls a tab, given the tab reference
        // Returns the button vm instance
        getButtonForTab: function getButtonForTab(tab) {
          return (this.$refs.buttons || []).find(function (btn) {
            return btn.tab === tab;
          });
        },
        // Force a button to re-render its content, given a <b-tab> instance
        // Called by <b-tab> on `update()`
        updateButton: function updateButton(tab) {
          var button = this.getButtonForTab(tab);
  
          if (button && button.$forceUpdate) {
            button.$forceUpdate();
          }
        },
        // Activate a tab given a <b-tab> instance
        // Also accessed by <b-tab>
        activateTab: function activateTab(tab) {
          var result = false;
  
          if (tab) {
            var index = this.tabs.indexOf(tab);
  
            if (!tab.disabled && index > -1 && index !== this.currentTab) {
              var tabEvt = new BvEvent('activate-tab', {
                cancelable: true,
                vueTarget: this,
                componentId: this.safeId()
              });
              this.$emit(tabEvt.type, index, this.currentTab, tabEvt);
  
              if (!tabEvt.defaultPrevented) {
                result = true;
                this.currentTab = index;
              }
            }
          } // Couldn't set tab, so ensure v-model is set to `this.currentTab`
  
          /* istanbul ignore next: should rarely happen */
  
  
          if (!result && this.currentTab !== this.value) {
            this.$emit('input', this.currentTab);
          }
  
          return result;
        },
        // Deactivate a tab given a <b-tab> instance
        // Accessed by <b-tab>
        deactivateTab: function deactivateTab(tab) {
          if (tab) {
            // Find first non-disabled tab that isn't the one being deactivated
            // If no tabs are available, then don't deactivate current tab
            return this.activateTab(this.tabs.filter(function (t) {
              return t !== tab;
            }).find(notDisabled));
          }
          /* istanbul ignore next: should never/rarely happen */
  
  
          return false;
        },
        // Focus a tab button given its <b-tab> instance
        focusButton: function focusButton(tab) {
          var _this8 = this;
  
          // Wrap in `$nextTick()` to ensure DOM has completed rendering/updating before focusing
          this.$nextTick(function () {
            var button = _this8.getButtonForTab(tab);
  
            if (button && button.focus) {
              button.focus();
            }
          });
        },
        // Emit a click event on a specified <b-tab> component instance
        emitTabClick: function emitTabClick(tab, evt) {
          if (isEvent(evt) && tab && tab.$emit && !tab.disabled) {
            tab.$emit('click', evt);
          }
        },
        // Click handler
        clickTab: function clickTab(tab, evt) {
          this.activateTab(tab);
          this.emitTabClick(tab, evt);
        },
        // Move to first non-disabled tab
        firstTab: function firstTab(focus) {
          var tab = this.tabs.find(notDisabled);
  
          if (this.activateTab(tab) && focus) {
            this.focusButton(tab);
            this.emitTabClick(tab, focus);
          }
        },
        // Move to previous non-disabled tab
        previousTab: function previousTab(focus) {
          var currentIndex = Math.max(this.currentTab, 0);
          var tab = this.tabs.slice(0, currentIndex).reverse().find(notDisabled);
  
          if (this.activateTab(tab) && focus) {
            this.focusButton(tab);
            this.emitTabClick(tab, focus);
          }
        },
        // Move to next non-disabled tab
        nextTab: function nextTab(focus) {
          var currentIndex = Math.max(this.currentTab, -1);
          var tab = this.tabs.slice(currentIndex + 1).find(notDisabled);
  
          if (this.activateTab(tab) && focus) {
            this.focusButton(tab);
            this.emitTabClick(tab, focus);
          }
        },
        // Move to last non-disabled tab
        lastTab: function lastTab(focus) {
          var tab = this.tabs.slice().reverse().find(notDisabled);
  
          if (this.activateTab(tab) && focus) {
            this.focusButton(tab);
            this.emitTabClick(tab, focus);
          }
        }
      },
      render: function render(h) {
        var _this9 = this;
  
        var tabs = this.tabs; // Currently active tab
  
        var activeTab = tabs.find(function (tab) {
          return tab.localActive && !tab.disabled;
        }); // Tab button to allow focusing when no active tab found (keynav only)
  
        var fallbackTab = tabs.find(function (tab) {
          return !tab.disabled;
        }); // For each <b-tab> found create the tab buttons
  
        var buttons = tabs.map(function (tab, index) {
          var tabIndex = null; // Ensure at least one tab button is focusable when keynav enabled (if possible)
  
          if (!_this9.noKeyNav) {
            // Buttons are not in tab index unless active, or a fallback tab
            tabIndex = -1;
  
            if (activeTab === tab || !activeTab && fallbackTab === tab) {
              // Place tab button in tab sequence
              tabIndex = null;
            }
          }
  
          return h(BTabButtonHelper, {
            key: tab._uid || index,
            ref: 'buttons',
            // Needed to make `this.$refs.buttons` an array
            refInFor: true,
            props: {
              tab: tab,
              tabs: tabs,
              id: tab.controlledBy || (tab.safeId ? tab.safeId("_BV_tab_button_") : null),
              controls: tab.safeId ? tab.safeId() : null,
              tabIndex: tabIndex,
              setSize: tabs.length,
              posInSet: index + 1,
              noKeyNav: _this9.noKeyNav
            },
            on: {
              click: function click(evt) {
                _this9.clickTab(tab, evt);
              },
              first: _this9.firstTab,
              prev: _this9.previousTab,
              next: _this9.nextTab,
              last: _this9.lastTab
            }
          });
        }); // Nav
  
        var nav = h(BNav, {
          ref: 'nav',
          class: this.localNavClass,
          attrs: {
            role: 'tablist',
            id: this.safeId('_BV_tab_controls_')
          },
          props: {
            fill: this.fill,
            justified: this.justified,
            align: this.align,
            tabs: !this.noNavStyle && !this.pills,
            pills: !this.noNavStyle && this.pills,
            vertical: this.vertical,
            small: this.small,
            cardHeader: this.card && !this.vertical
          }
        }, [this.normalizeSlot('tabs-start') || h(), buttons, this.normalizeSlot('tabs-end') || h()]);
        nav = h('div', {
          key: 'bv-tabs-nav',
          class: [{
            'card-header': this.card && !this.vertical && !this.end,
            'card-footer': this.card && !this.vertical && this.end,
            'col-auto': this.vertical
          }, this.navWrapperClass]
        }, [nav]);
        var empty = h();
  
        if (!tabs || tabs.length === 0) {
          empty = h('div', {
            key: 'bv-empty-tab',
            class: ['tab-pane', 'active', {
              'card-body': this.card
            }]
          }, this.normalizeSlot('empty'));
        } // Main content section
  
  
        var content = h('div', {
          ref: 'tabsContainer',
          key: 'bv-tabs-container',
          staticClass: 'tab-content',
          class: [{
            col: this.vertical
          }, this.contentClass],
          attrs: {
            id: this.safeId('_BV_tab_container_')
          }
        }, concat(this.normalizeSlot('default'), empty)); // Render final output
  
        return h(this.tag, {
          staticClass: 'tabs',
          class: {
            row: this.vertical,
            'no-gutters': this.vertical && this.card
          },
          attrs: {
            id: this.safeId()
          }
        }, [this.end ? content : h(), [nav], this.end ? h() : content]);
      }
    });
  
    var BTab = /*#__PURE__*/Vue.extend({
      name: 'BTab',
      mixins: [idMixin, normalizeSlotMixin],
      inject: {
        bvTabs: {
          default: function _default() {
            return {};
          }
        }
      },
      props: {
        active: {
          type: Boolean,
          default: false
        },
        tag: {
          type: String,
          default: 'div'
        },
        buttonId: {
          type: String,
          default: ''
        },
        title: {
          type: String,
          default: ''
        },
        titleItemClass: {
          // Sniffed by tabs.js and added to nav 'li.nav-item'
          type: [String, Array, Object],
          default: null
        },
        titleLinkClass: {
          // Sniffed by tabs.js and added to nav 'a.nav-link'
          type: [String, Array, Object],
          default: null
        },
        titleLinkAttributes: {
          type: Object,
          default: null
        },
        disabled: {
          type: Boolean,
          default: false
        },
        noBody: {
          type: Boolean,
          default: false
        },
        lazy: {
          type: Boolean,
          default: false
        }
      },
      data: function data() {
        return {
          localActive: this.active && !this.disabled,
          show: false
        };
      },
      computed: {
        tabClasses: function tabClasses() {
          return [{
            active: this.localActive,
            disabled: this.disabled,
            'card-body': this.bvTabs.card && !this.noBody
          }, // Apply <b-tabs> `activeTabClass` styles when this tab is active
          this.localActive ? this.bvTabs.activeTabClass : null];
        },
        controlledBy: function controlledBy() {
          return this.buttonId || this.safeId('__BV_tab_button__');
        },
        computedNoFade: function computedNoFade() {
          return !(this.bvTabs.fade || false);
        },
        computedLazy: function computedLazy() {
          return this.bvTabs.lazy || this.lazy;
        },
        _isTab: function _isTab() {
          // For parent sniffing of child
          return true;
        }
      },
      watch: {
        localActive: function localActive(newVal) {
          // Make 'active' prop work with `.sync` modifier
          this.$emit('update:active', newVal);
        },
        active: function active(newVal, oldVal) {
          if (newVal !== oldVal) {
            if (newVal) {
              // If activated post mount
              this.activate();
            } else {
              /* istanbul ignore next */
              if (!this.deactivate()) {
                // Tab couldn't be deactivated, so we reset the synced active prop
                // Deactivation will fail if no other tabs to activate
                this.$emit('update:active', this.localActive);
              }
            }
          }
        },
        disabled: function disabled(newVal, oldVal) {
          if (newVal !== oldVal) {
            if (newVal && this.localActive && this.bvTabs.firstTab) {
              this.localActive = false;
              this.bvTabs.firstTab();
            }
          }
        }
      },
      mounted: function mounted() {
        // Inform b-tabs of our presence
        this.registerTab(); // Initially show on mount if active and not disabled
  
        this.show = this.localActive;
      },
      updated: function updated() {
        // Force the tab button content to update (since slots are not reactive)
        // Only done if we have a title slot, as the title prop is reactive
        if (this.hasNormalizedSlot('title') && this.bvTabs.updateButton) {
          this.bvTabs.updateButton(this);
        }
      },
      destroyed: function destroyed() {
        // inform b-tabs of our departure
        this.unregisterTab();
      },
      methods: {
        // Private methods
        registerTab: function registerTab() {
          // Inform `b-tabs` of our presence
          this.bvTabs.registerTab && this.bvTabs.registerTab(this);
        },
        unregisterTab: function unregisterTab() {
          // Inform `b-tabs` of our departure
          this.bvTabs.unregisterTab && this.bvTabs.unregisterTab(this);
        },
        // Public methods
        activate: function activate() {
          if (this.bvTabs.activateTab && !this.disabled) {
            return this.bvTabs.activateTab(this);
          } else {
            // Not inside a <b-tabs> component or tab is disabled
            return false;
          }
        },
        deactivate: function deactivate() {
          if (this.bvTabs.deactivateTab && this.localActive) {
            return this.bvTabs.deactivateTab(this);
          } else {
            // Not inside a <b-tabs> component or not active to begin with
            return false;
          }
        }
      },
      render: function render(h) {
        var content = h(this.tag, {
          ref: 'panel',
          staticClass: 'tab-pane',
          class: this.tabClasses,
          directives: [{
            name: 'show',
            rawName: 'v-show',
            value: this.localActive,
            expression: 'localActive'
          }],
          attrs: {
            role: 'tabpanel',
            id: this.safeId(),
            'aria-hidden': this.localActive ? 'false' : 'true',
            'aria-labelledby': this.controlledBy || null
          }
        }, // Render content lazily if requested
        [this.localActive || !this.computedLazy ? this.normalizeSlot('default') : h()]);
        return h(BVTransition, {
          props: {
            mode: 'out-in',
            noFade: this.computedNoFade
          }
        }, [content]);
      }
    });
  
    var TabsPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BTabs: BTabs,
        BTab: BTab
      }
    });
  
    var TimePlugin = /*#__PURE__*/pluginFactory({
      components: {
        BTime: BTime
      }
    });
  
    function _typeof$1(obj) {
      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
        _typeof$1 = function (obj) {
          return typeof obj;
        };
      } else {
        _typeof$1 = function (obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
      }
  
      return _typeof$1(obj);
    }
  
    function _toConsumableArray$1(arr) {
      return _arrayWithoutHoles$1(arr) || _iterableToArray$1(arr) || _nonIterableSpread$1();
    }
  
    function _arrayWithoutHoles$1(arr) {
      if (Array.isArray(arr)) {
        for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
  
        return arr2;
      }
    }
  
    function _iterableToArray$1(iter) {
      if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
    }
  
    function _nonIterableSpread$1() {
      throw new TypeError("Invalid attempt to spread non-iterable instance");
    }
  
    var inBrowser = typeof window !== 'undefined';
    function freeze$1(item) {
      if (Array.isArray(item) || _typeof$1(item) === 'object') {
        return Object.freeze(item);
      }
  
      return item;
    }
    function combinePassengers(transports) {
      var slotProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      return transports.reduce(function (passengers, transport) {
        var temp = transport.passengers[0];
        var newPassengers = typeof temp === 'function' ? temp(slotProps) : transport.passengers;
        return passengers.concat(newPassengers);
      }, []);
    }
    function stableSort$1(array, compareFn) {
      return array.map(function (v, idx) {
        return [idx, v];
      }).sort(function (a, b) {
        return compareFn(a[1], b[1]) || a[0] - b[0];
      }).map(function (c) {
        return c[1];
      });
    }
    function pick(obj, keys) {
      return keys.reduce(function (acc, key) {
        if (obj.hasOwnProperty(key)) {
          acc[key] = obj[key];
        }
  
        return acc;
      }, {});
    }
  
    var transports = {};
    var targets = {};
    var sources = {};
    var Wormhole = Vue.extend({
      data: function data() {
        return {
          transports: transports,
          targets: targets,
          sources: sources,
          trackInstances: inBrowser
        };
      },
      methods: {
        open: function open(transport) {
          if (!inBrowser) return;
          var to = transport.to,
              from = transport.from,
              passengers = transport.passengers,
              _transport$order = transport.order,
              order = _transport$order === void 0 ? Infinity : _transport$order;
          if (!to || !from || !passengers) return;
          var newTransport = {
            to: to,
            from: from,
            passengers: freeze$1(passengers),
            order: order
          };
          var keys = Object.keys(this.transports);
  
          if (keys.indexOf(to) === -1) {
            Vue.set(this.transports, to, []);
          }
  
          var currentIndex = this.$_getTransportIndex(newTransport); // Copying the array here so that the PortalTarget change event will actually contain two distinct arrays
  
          var newTransports = this.transports[to].slice(0);
  
          if (currentIndex === -1) {
            newTransports.push(newTransport);
          } else {
            newTransports[currentIndex] = newTransport;
          }
  
          this.transports[to] = stableSort$1(newTransports, function (a, b) {
            return a.order - b.order;
          });
        },
        close: function close(transport) {
          var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
          var to = transport.to,
              from = transport.from;
          if (!to || !from && force === false) return;
  
          if (!this.transports[to]) {
            return;
          }
  
          if (force) {
            this.transports[to] = [];
          } else {
            var index = this.$_getTransportIndex(transport);
  
            if (index >= 0) {
              // Copying the array here so that the PortalTarget change event will actually contain two distinct arrays
              var newTransports = this.transports[to].slice(0);
              newTransports.splice(index, 1);
              this.transports[to] = newTransports;
            }
          }
        },
        registerTarget: function registerTarget(target, vm, force) {
          if (!inBrowser) return;
  
          if (this.trackInstances && !force && this.targets[target]) {
            console.warn("[portal-vue]: Target ".concat(target, " already exists"));
          }
  
          this.$set(this.targets, target, Object.freeze([vm]));
        },
        unregisterTarget: function unregisterTarget(target) {
          this.$delete(this.targets, target);
        },
        registerSource: function registerSource(source, vm, force) {
          if (!inBrowser) return;
  
          if (this.trackInstances && !force && this.sources[source]) {
            console.warn("[portal-vue]: source ".concat(source, " already exists"));
          }
  
          this.$set(this.sources, source, Object.freeze([vm]));
        },
        unregisterSource: function unregisterSource(source) {
          this.$delete(this.sources, source);
        },
        hasTarget: function hasTarget(to) {
          return !!(this.targets[to] && this.targets[to][0]);
        },
        hasSource: function hasSource(to) {
          return !!(this.sources[to] && this.sources[to][0]);
        },
        hasContentFor: function hasContentFor(to) {
          return !!this.transports[to] && !!this.transports[to].length;
        },
        // Internal
        $_getTransportIndex: function $_getTransportIndex(_ref) {
          var to = _ref.to,
              from = _ref.from;
  
          for (var i in this.transports[to]) {
            if (this.transports[to][i].from === from) {
              return +i;
            }
          }
  
          return -1;
        }
      }
    });
    var wormhole = new Wormhole(transports);
  
    var _id = 1;
    var Portal = Vue.extend({
      name: 'portal',
      props: {
        disabled: {
          type: Boolean
        },
        name: {
          type: String,
          default: function _default() {
            return String(_id++);
          }
        },
        order: {
          type: Number,
          default: 0
        },
        slim: {
          type: Boolean
        },
        slotProps: {
          type: Object,
          default: function _default() {
            return {};
          }
        },
        tag: {
          type: String,
          default: 'DIV'
        },
        to: {
          type: String,
          default: function _default() {
            return String(Math.round(Math.random() * 10000000));
          }
        }
      },
      created: function created() {
        var _this = this;
  
        this.$nextTick(function () {
          wormhole.registerSource(_this.name, _this);
        });
      },
      mounted: function mounted() {
        if (!this.disabled) {
          this.sendUpdate();
        }
      },
      updated: function updated() {
        if (this.disabled) {
          this.clear();
        } else {
          this.sendUpdate();
        }
      },
      beforeDestroy: function beforeDestroy() {
        wormhole.unregisterSource(this.name);
        this.clear();
      },
      watch: {
        to: function to(newValue, oldValue) {
          oldValue && oldValue !== newValue && this.clear(oldValue);
          this.sendUpdate();
        }
      },
      methods: {
        clear: function clear(target) {
          var closer = {
            from: this.name,
            to: target || this.to
          };
          wormhole.close(closer);
        },
        normalizeSlots: function normalizeSlots() {
          return this.$scopedSlots.default ? [this.$scopedSlots.default] : this.$slots.default;
        },
        normalizeOwnChildren: function normalizeOwnChildren(children) {
          return typeof children === 'function' ? children(this.slotProps) : children;
        },
        sendUpdate: function sendUpdate() {
          var slotContent = this.normalizeSlots();
  
          if (slotContent) {
            var transport = {
              from: this.name,
              to: this.to,
              passengers: _toConsumableArray$1(slotContent),
              order: this.order
            };
            wormhole.open(transport);
          } else {
            this.clear();
          }
        }
      },
      render: function render(h) {
        var children = this.$slots.default || this.$scopedSlots.default || [];
        var Tag = this.tag;
  
        if (children && this.disabled) {
          return children.length <= 1 && this.slim ? this.normalizeOwnChildren(children)[0] : h(Tag, [this.normalizeOwnChildren(children)]);
        } else {
          return this.slim ? h() : h(Tag, {
            class: {
              'v-portal': true
            },
            style: {
              display: 'none'
            },
            key: 'v-portal-placeholder'
          });
        }
      }
    });
  
    var PortalTarget = Vue.extend({
      name: 'portalTarget',
      props: {
        multiple: {
          type: Boolean,
          default: false
        },
        name: {
          type: String,
          required: true
        },
        slim: {
          type: Boolean,
          default: false
        },
        slotProps: {
          type: Object,
          default: function _default() {
            return {};
          }
        },
        tag: {
          type: String,
          default: 'div'
        },
        transition: {
          type: [String, Object, Function]
        }
      },
      data: function data() {
        return {
          transports: wormhole.transports,
          firstRender: true
        };
      },
      created: function created() {
        var _this = this;
  
        this.$nextTick(function () {
          wormhole.registerTarget(_this.name, _this);
        });
      },
      watch: {
        ownTransports: function ownTransports() {
          this.$emit('change', this.children().length > 0);
        },
        name: function name(newVal, oldVal) {
          /**
           * TODO
           * This should warn as well ...
           */
          wormhole.unregisterTarget(oldVal);
          wormhole.registerTarget(newVal, this);
        }
      },
      mounted: function mounted() {
        var _this2 = this;
  
        if (this.transition) {
          this.$nextTick(function () {
            // only when we have a transition, because it causes a re-render
            _this2.firstRender = false;
          });
        }
      },
      beforeDestroy: function beforeDestroy() {
        wormhole.unregisterTarget(this.name);
      },
      computed: {
        ownTransports: function ownTransports() {
          var transports = this.transports[this.name] || [];
  
          if (this.multiple) {
            return transports;
          }
  
          return transports.length === 0 ? [] : [transports[transports.length - 1]];
        },
        passengers: function passengers() {
          return combinePassengers(this.ownTransports, this.slotProps);
        }
      },
      methods: {
        // can't be a computed prop because it has to "react" to $slot changes.
        children: function children() {
          return this.passengers.length !== 0 ? this.passengers : this.$scopedSlots.default ? this.$scopedSlots.default(this.slotProps) : this.$slots.default || [];
        },
        // can't be a computed prop because it has to "react" to this.children().
        noWrapper: function noWrapper() {
          var noWrapper = this.slim && !this.transition;
  
          if (noWrapper && this.children().length > 1) {
            console.warn('[portal-vue]: PortalTarget with `slim` option received more than one child element.');
          }
  
          return noWrapper;
        }
      },
      render: function render(h) {
        var noWrapper = this.noWrapper();
        var children = this.children();
        var Tag = this.transition || this.tag;
        return noWrapper ? children[0] : this.slim && !Tag ? h() : h(Tag, {
          props: {
            // if we have a transition component, pass the tag if it exists
            tag: this.transition && this.tag ? this.tag : undefined
          },
          class: {
            'vue-portal-target': true
          }
        }, children);
      }
    });
  
    var _id$1 = 0;
    var portalProps = ['disabled', 'name', 'order', 'slim', 'slotProps', 'tag', 'to'];
    var targetProps = ['multiple', 'transition'];
    var MountingPortal = Vue.extend({
      name: 'MountingPortal',
      inheritAttrs: false,
      props: {
        append: {
          type: [Boolean, String]
        },
        bail: {
          type: Boolean
        },
        mountTo: {
          type: String,
          required: true
        },
        // Portal
        disabled: {
          type: Boolean
        },
        // name for the portal
        name: {
          type: String,
          default: function _default() {
            return 'mounted_' + String(_id$1++);
          }
        },
        order: {
          type: Number,
          default: 0
        },
        slim: {
          type: Boolean
        },
        slotProps: {
          type: Object,
          default: function _default() {
            return {};
          }
        },
        tag: {
          type: String,
          default: 'DIV'
        },
        // name for the target
        to: {
          type: String,
          default: function _default() {
            return String(Math.round(Math.random() * 10000000));
          }
        },
        // Target
        multiple: {
          type: Boolean,
          default: false
        },
        targetSlim: {
          type: Boolean
        },
        targetSlotProps: {
          type: Object,
          default: function _default() {
            return {};
          }
        },
        targetTag: {
          type: String,
          default: 'div'
        },
        transition: {
          type: [String, Object, Function]
        }
      },
      created: function created() {
        if (typeof document === 'undefined') return;
        var el = document.querySelector(this.mountTo);
  
        if (!el) {
          console.error("[portal-vue]: Mount Point '".concat(this.mountTo, "' not found in document"));
          return;
        }
  
        var props = this.$props; // Target already exists
  
        if (wormhole.targets[props.name]) {
          if (props.bail) {
            console.warn("[portal-vue]: Target ".concat(props.name, " is already mounted.\n        Aborting because 'bail: true' is set"));
          } else {
            this.portalTarget = wormhole.targets[props.name];
          }
  
          return;
        }
  
        var append = props.append;
  
        if (append) {
          var type = typeof append === 'string' ? append : 'DIV';
          var mountEl = document.createElement(type);
          el.appendChild(mountEl);
          el = mountEl;
        } // get props for target from $props
        // we have to rename a few of them
  
  
        var _props = pick(this.$props, targetProps);
  
        _props.slim = this.targetSlim;
        _props.tag = this.targetTag;
        _props.slotProps = this.targetSlotProps;
        _props.name = this.to;
        this.portalTarget = new PortalTarget({
          el: el,
          parent: this.$parent || this,
          propsData: _props
        });
      },
      beforeDestroy: function beforeDestroy() {
        var target = this.portalTarget;
  
        if (this.append) {
          var el = target.$el;
          el.parentNode.removeChild(el);
        }
  
        target.$destroy();
      },
      render: function render(h) {
        if (!this.portalTarget) {
          console.warn("[portal-vue] Target wasn't mounted");
          return h();
        } // if there's no "manual" scoped slot, so we create a <Portal> ourselves
  
  
        if (!this.$scopedSlots.manual) {
          var props = pick(this.$props, portalProps);
          return h(Portal, {
            props: props,
            attrs: this.$attrs,
            on: this.$listeners,
            scopedSlots: this.$scopedSlots
          }, this.$slots.default);
        } // else, we render the scoped slot
  
  
        var content = this.$scopedSlots.manual({
          to: this.to
        }); // if user used <template> for the scoped slot
        // content will be an array
  
        if (Array.isArray(content)) {
          content = content[0];
        }
  
        if (!content) return h();
        return content;
      }
    });
  
    var NAME$E = 'BToaster';
    var props$Z = {
      name: {
        type: String,
        required: true
      },
      ariaLive: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$E, 'ariaLive');
        }
      },
      ariaAtomic: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$E, 'ariaAtomic');
        } // Allowed: 'true' or 'false' or null
  
      },
      role: {
        // Aria role
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$E, 'role');
        }
      }
      /*
      transition: {
        type: [Boolean, String, Object],
        default: false
      }
      */
  
    }; // @vue/component
  
    var DefaultTransition = /*#__PURE__*/Vue.extend({
      data: function data() {
        return {
          // Transition classes base name
          name: 'b-toaster'
        };
      },
      methods: {
        onAfterEnter: function onAfterEnter(el) {
          var _this = this;
  
          // Handle bug where enter-to class is not removed.
          // Bug is related to portal-vue and transition-groups.
          requestAF(function () {
            removeClass(el, "".concat(_this.name, "-enter-to")); // The *-move class is also stuck on elements that moved,
            // but there are no javascript hooks to handle after move.
          });
        }
      },
      render: function render(h) {
        return h('transition-group', {
          props: {
            tag: 'div',
            name: this.name
          },
          on: {
            afterEnter: this.onAfterEnter
          }
        }, this.$slots.default);
      }
    }); // @vue/component
  
    var BToaster = /*#__PURE__*/Vue.extend({
      name: NAME$E,
      props: props$Z,
      data: function data() {
        return {
          // We don't render on SSR or if a an existing target found
          doRender: false,
          dead: false,
          // Toaster names cannot change once created
          staticName: this.name
        };
      },
      beforeMount: function beforeMount() {
        var _this2 = this;
  
        this.staticName = this.name;
        /* istanbul ignore if */
  
        if (wormhole.hasTarget(this.staticName)) {
          warn("A \"<portal-target>\" with name \"".concat(this.name, "\" already exists in the document."), 'BToaster');
          this.dead = true;
        } else {
          this.doRender = true;
          this.$once('hook:beforeDestroy', function () {
            // Let toasts made with `this.$bvToast.toast()` know that this toaster
            // is being destroyed and should should also destroy/hide themselves
            _this2.$root.$emit('bv::toaster::destroyed', _this2.staticName);
          });
        }
      },
      destroyed: function destroyed() {
        // Remove from DOM if needed
  
        /* istanbul ignore next: difficult to test */
        if (this.$el && this.$el.parentNode) {
          this.$el.parentNode.removeChild(this.$el);
        }
      },
      render: function render(h) {
        var $toaster = h('div', {
          class: ['d-none', {
            'b-dead-toaster': this.dead
          }]
        });
  
        if (this.doRender) {
          var $target = h(PortalTarget, {
            staticClass: 'b-toaster-slot',
            props: {
              name: this.staticName,
              multiple: true,
              tag: 'div',
              slim: false,
              // transition: this.transition || DefaultTransition
              transition: DefaultTransition
            }
          });
          $toaster = h('div', {
            staticClass: 'b-toaster',
            class: [this.staticName],
            attrs: {
              id: this.staticName,
              role: this.role || null,
              // Fallback to null to make sure attribute doesn't exist
              'aria-live': this.ariaLive,
              'aria-atomic': this.ariaAtomic
            }
          }, [$target]);
        }
  
        return $toaster;
      }
    });
  
    var NAME$F = 'BToast';
    var MIN_DURATION = 1000; // --- Props ---
  
    var props$_ = {
      id: {
        // Even though the ID prop is provided by idMixin, we
        // add it here for $bvToast props filtering
        type: String,
        default: null
      },
      title: {
        type: String,
        default: null
      },
      toaster: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$F, 'toaster');
        }
      },
      visible: {
        type: Boolean,
        default: false
      },
      variant: {
        type: String,
        default: function _default() {
          return getComponentConfig(NAME$F, 'variant');
        }
      },
      isStatus: {
        // Switches role to 'status' and aria-live to 'polite'
        type: Boolean,
        default: false
      },
      appendToast: {
        type: Boolean,
        default: false
      },
      noAutoHide: {
        type: Boolean,
        default: false
      },
      autoHideDelay: {
        type: [Number, String],
        default: function _default() {
          return getComponentConfig(NAME$F, 'autoHideDelay');
        }
      },
      noCloseButton: {
        type: Boolean,
        default: false
      },
      noFade: {
        type: Boolean,
        default: false
      },
      noHoverPause: {
        type: Boolean,
        default: false
      },
      solid: {
        type: Boolean,
        default: false
      },
      toastClass: {
        type: [String, Object, Array],
        default: function _default() {
          return getComponentConfig(NAME$F, 'toastClass');
        }
      },
      headerClass: {
        type: [String, Object, Array],
        default: function _default() {
          return getComponentConfig(NAME$F, 'headerClass');
        }
      },
      bodyClass: {
        type: [String, Object, Array],
        default: function _default() {
          return getComponentConfig(NAME$F, 'bodyClass');
        }
      },
      href: {
        type: String,
        default: null
      },
      to: {
        type: [String, Object],
        default: null
      },
      static: {
        // Render the toast in place, rather than in a portal-target
        type: Boolean,
        default: false
      }
    }; // @vue/component
  
    var BToast = /*#__PURE__*/Vue.extend({
      name: NAME$F,
      mixins: [idMixin, listenOnRootMixin, normalizeSlotMixin, scopedStyleAttrsMixin],
      inheritAttrs: false,
      model: {
        prop: 'visible',
        event: 'change'
      },
      props: props$_,
      data: function data() {
        return {
          isMounted: false,
          doRender: false,
          localShow: false,
          isTransitioning: false,
          isHiding: false,
          order: 0,
          timer: null,
          dismissStarted: 0,
          resumeDismiss: 0
        };
      },
      computed: {
        bToastClasses: function bToastClasses() {
          return _defineProperty({
            'b-toast-solid': this.solid,
            'b-toast-append': this.appendToast,
            'b-toast-prepend': !this.appendToast
          }, "b-toast-".concat(this.variant), this.variant);
        },
        slotScope: function slotScope() {
          return {
            hide: this.hide
          };
        },
        computedDuration: function computedDuration() {
          // Minimum supported duration is 1 second
          return Math.max(toInteger(this.autoHideDelay) || 0, MIN_DURATION);
        },
        computedToaster: function computedToaster() {
          return String(this.toaster);
        },
        transitionHandlers: function transitionHandlers() {
          return {
            beforeEnter: this.onBeforeEnter,
            afterEnter: this.onAfterEnter,
            beforeLeave: this.onBeforeLeave,
            afterLeave: this.onAfterLeave
          };
        }
      },
      watch: {
        visible: function visible(newVal) {
          newVal ? this.show() : this.hide();
        },
        localShow: function localShow(newVal) {
          if (newVal !== this.visible) {
            this.$emit('change', newVal);
          }
        },
        toaster: function toaster()
        /* istanbul ignore next */
        {
          // If toaster target changed, make sure toaster exists
          this.$nextTick(this.ensureToaster);
        },
        static: function _static(newVal)
        /* istanbul ignore next */
        {
          // If static changes to true, and the toast is showing,
          // ensure the toaster target exists
          if (newVal && this.localShow) {
            this.ensureToaster();
          }
        }
      },
      mounted: function mounted() {
        var _this = this;
  
        this.isMounted = true;
        this.$nextTick(function () {
          if (_this.visible) {
            requestAF(function () {
              _this.show();
            });
          }
        }); // Listen for global $root show events
  
        this.listenOnRoot('bv::show::toast', function (id) {
          if (id === _this.safeId()) {
            _this.show();
          }
        }); // Listen for global $root hide events
  
        this.listenOnRoot('bv::hide::toast', function (id) {
          if (!id || id === _this.safeId()) {
            _this.hide();
          }
        }); // Make sure we hide when toaster is destroyed
  
        /* istanbul ignore next: difficult to test */
  
        this.listenOnRoot('bv::toaster::destroyed', function (toaster) {
          /* istanbul ignore next */
          if (toaster === _this.computedToaster) {
            /* istanbul ignore next */
            _this.hide();
          }
        });
      },
      beforeDestroy: function beforeDestroy() {
        this.clearDismissTimer();
      },
      methods: {
        show: function show() {
          var _this2 = this;
  
          if (!this.localShow) {
            this.ensureToaster();
            var showEvt = this.buildEvent('show');
            this.emitEvent(showEvt);
            this.dismissStarted = this.resumeDismiss = 0;
            this.order = Date.now() * (this.appendToast ? 1 : -1);
            this.isHiding = false;
            this.doRender = true;
            this.$nextTick(function () {
              // We show the toast after we have rendered the portal and b-toast wrapper
              // so that screen readers will properly announce the toast
              requestAF(function () {
                _this2.localShow = true;
              });
            });
          }
        },
        hide: function hide() {
          var _this3 = this;
  
          if (this.localShow) {
            var hideEvt = this.buildEvent('hide');
            this.emitEvent(hideEvt);
            this.setHoverHandler(false);
            this.dismissStarted = this.resumeDismiss = 0;
            this.clearDismissTimer();
            this.isHiding = true;
            requestAF(function () {
              _this3.localShow = false;
            });
          }
        },
        buildEvent: function buildEvent(type) {
          var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
          return new BvEvent(type, _objectSpread2({
            cancelable: false,
            target: this.$el || null,
            relatedTarget: null
          }, options, {
            vueTarget: this,
            componentId: this.safeId()
          }));
        },
        emitEvent: function emitEvent(bvEvt) {
          var type = bvEvt.type;
          this.$root.$emit("bv::toast:".concat(type), bvEvt);
          this.$emit(type, bvEvt);
        },
        ensureToaster: function ensureToaster() {
          if (this.static) {
            return;
          }
  
          if (!wormhole.hasTarget(this.computedToaster)) {
            var div = document.createElement('div');
            document.body.appendChild(div);
            var toaster = new BToaster({
              parent: this.$root,
              propsData: {
                name: this.computedToaster
              }
            });
            toaster.$mount(div);
          }
        },
        startDismissTimer: function startDismissTimer() {
          this.clearDismissTimer();
  
          if (!this.noAutoHide) {
            this.timer = setTimeout(this.hide, this.resumeDismiss || this.computedDuration);
            this.dismissStarted = Date.now();
            this.resumeDismiss = 0;
          }
        },
        clearDismissTimer: function clearDismissTimer() {
          clearTimeout(this.timer);
          this.timer = null;
        },
        setHoverHandler: function setHoverHandler(on) {
          var el = this.$refs['b-toast'];
          eventOnOff(on, el, 'mouseenter', this.onPause, EVENT_OPTIONS_NO_CAPTURE);
          eventOnOff(on, el, 'mouseleave', this.onUnPause, EVENT_OPTIONS_NO_CAPTURE);
        },
        onPause: function onPause() {
          // Determine time remaining, and then pause timer
          if (this.noAutoHide || this.noHoverPause || !this.timer || this.resumeDismiss) {
            return;
          }
  
          var passed = Date.now() - this.dismissStarted;
  
          if (passed > 0) {
            this.clearDismissTimer();
            this.resumeDismiss = Math.max(this.computedDuration - passed, MIN_DURATION);
          }
        },
        onUnPause: function onUnPause() {
          // Restart timer with max of time remaining or 1 second
          if (this.noAutoHide || this.noHoverPause || !this.resumeDismiss) {
            this.resumeDismiss = this.dismissStarted = 0;
            return;
          }
  
          this.startDismissTimer();
        },
        onLinkClick: function onLinkClick() {
          var _this4 = this;
  
          // We delay the close to allow time for the
          // browser to process the link click
          this.$nextTick(function () {
            requestAF(function () {
              _this4.hide();
            });
          });
        },
        onBeforeEnter: function onBeforeEnter() {
          this.isTransitioning = true;
        },
        onAfterEnter: function onAfterEnter() {
          this.isTransitioning = false;
          var hiddenEvt = this.buildEvent('shown');
          this.emitEvent(hiddenEvt);
          this.startDismissTimer();
          this.setHoverHandler(true);
        },
        onBeforeLeave: function onBeforeLeave() {
          this.isTransitioning = true;
        },
        onAfterLeave: function onAfterLeave() {
          this.isTransitioning = false;
          this.order = 0;
          this.resumeDismiss = this.dismissStarted = 0;
          var hiddenEvt = this.buildEvent('hidden');
          this.emitEvent(hiddenEvt);
          this.doRender = false;
        },
        makeToast: function makeToast(h) {
          var _this5 = this;
  
          // Render helper for generating the toast
          // Assemble the header content
          var $headerContent = [];
          var $title = this.normalizeSlot('toast-title', this.slotScope);
  
          if ($title) {
            $headerContent.push($title);
          } else if (this.title) {
            $headerContent.push(h('strong', {
              staticClass: 'mr-2'
            }, this.title));
          }
  
          if (!this.noCloseButton) {
            $headerContent.push(h(BButtonClose, {
              staticClass: 'ml-auto mb-1',
              on: {
                click: function click() {
                  _this5.hide();
                }
              }
            }));
          } // Assemble the header (if needed)
  
  
          var $header = h();
  
          if ($headerContent.length > 0) {
            $header = h('header', {
              staticClass: 'toast-header',
              class: this.headerClass
            }, $headerContent);
          } // Toast body
  
  
          var isLink = this.href || this.to;
          var $body = h(isLink ? BLink : 'div', {
            staticClass: 'toast-body',
            class: this.bodyClass,
            props: isLink ? {
              to: this.to,
              href: this.href
            } : {},
            on: isLink ? {
              click: this.onLinkClick
            } : {}
          }, [this.normalizeSlot('default', this.slotScope) || h()]); // Build the toast
  
          var $toast = h('div', {
            key: "toast-".concat(this._uid),
            ref: 'toast',
            staticClass: 'toast',
            class: this.toastClass,
            attrs: _objectSpread2({}, this.$attrs, {
              tabindex: '0',
              id: this.safeId()
            })
          }, [$header, $body]);
          return $toast;
        }
      },
      render: function render(h) {
        if (!this.doRender || !this.isMounted) {
          return h();
        }
  
        var name = "b-toast-".concat(this._uid); // If scoped styles are applied and the toast is not static,
        // make sure the scoped style data attribute is applied
  
        var scopedStyleAttrs = !this.static ? this.scopedStyleAttrs : {};
        return h(Portal, {
          props: {
            name: name,
            to: this.computedToaster,
            order: this.order,
            slim: true,
            disabled: this.static
          }
        }, [h('div', {
          key: name,
          ref: 'b-toast',
          staticClass: 'b-toast',
          class: this.bToastClasses,
          attrs: _objectSpread2({}, scopedStyleAttrs, {
            id: this.safeId('_toast_outer'),
            role: this.isHiding ? null : this.isStatus ? 'status' : 'alert',
            'aria-live': this.isHiding ? null : this.isStatus ? 'polite' : 'assertive',
            'aria-atomic': this.isHiding ? null : 'true'
          })
        }, [h(BVTransition, {
          props: {
            noFade: this.noFade
          },
          on: this.transitionHandlers
        }, [this.localShow ? this.makeToast(h) : h()])])]);
      }
    });
  
    var PROP_NAME$3 = '$bvToast';
    var PROP_NAME_PRIV$1 = '_bv__toast'; // Base toast props that are allowed
    // Some may be ignored or overridden on some message boxes
    // Prop ID is allowed, but really only should be used for testing
    // We need to add it in explicitly as it comes from the `idMixin`
  
    var BASE_PROPS$1 = ['id'].concat(_toConsumableArray(keys(omit(props$_, ['static', 'visible'])))); // Map prop names to toast slot names
  
    var propsToSlots$1 = {
      toastContent: 'default',
      title: 'toast-title'
    }; // --- Utility methods ---
    // Method to filter only recognized props that are not undefined
  
    var filterOptions$1 = function filterOptions(options) {
      return BASE_PROPS$1.reduce(function (memo, key) {
        if (!isUndefined(options[key])) {
          memo[key] = options[key];
        }
  
        return memo;
      }, {});
    }; // Method to install `$bvToast` VM injection
  
  
    var plugin$1 = function plugin(Vue) {
      // Create a private sub-component constructor that
      // extends BToast and self-destructs after hidden
      // @vue/component
      var BToastPop = Vue.extend({
        name: 'BToastPop',
        extends: BToast,
        destroyed: function destroyed() {
          // Make sure we not in document any more
          if (this.$el && this.$el.parentNode) {
            this.$el.parentNode.removeChild(this.$el);
          }
        },
        mounted: function mounted() {
          var self = this; // Self destruct handler
  
          var handleDestroy = function handleDestroy() {
            // Ensure the toast has been force hidden
            self.localShow = false;
            self.doRender = false;
            self.$nextTick(function () {
              self.$nextTick(function () {
                // In a `requestAF()` to release control back to application
                // and to allow the portal-target time to remove the content
                requestAF(function () {
                  self.$destroy();
                });
              });
            });
          }; // Self destruct if parent destroyed
  
  
          this.$parent.$once('hook:destroyed', handleDestroy); // Self destruct after hidden
  
          this.$once('hidden', handleDestroy); // Self destruct when toaster is destroyed
  
          this.listenOnRoot('bv::toaster::destroyed', function (toaster) {
            /* istanbul ignore next: hard to test */
            if (toaster === self.toaster) {
              handleDestroy();
            }
          });
        }
      }); // Private method to generate the on-demand toast
  
      var makeToast = function makeToast(props, $parent) {
        if (warnNotClient(PROP_NAME$3)) {
          /* istanbul ignore next */
          return;
        } // Create an instance of `BToastPop` component
  
  
        var toast = new BToastPop({
          // We set parent as the local VM so these toasts can emit events on the
          // app `$root`, and it ensures `BToast` is destroyed when parent is destroyed
          parent: $parent,
          propsData: _objectSpread2({}, filterOptions$1(getComponentConfig('BToast') || {}), {}, omit(props, keys(propsToSlots$1)), {
            // Props that can't be overridden
            static: false,
            visible: true
          })
        }); // Convert certain props to slots
  
        keys(propsToSlots$1).forEach(function (prop) {
          var value = props[prop];
  
          if (!isUndefined(value)) {
            // Can be a string, or array of VNodes
            if (prop === 'title' && isString(value)) {
              // Special case for title if it is a string, we wrap in a <strong>
              value = [$parent.$createElement('strong', {
                class: 'mr-2'
              }, value)];
            }
  
            toast.$slots[propsToSlots$1[prop]] = concat(value);
          }
        }); // Create a mount point (a DIV) and mount it (which triggers the show)
  
        var div = document.createElement('div');
        document.body.appendChild(div);
        toast.$mount(div);
      }; // Declare BvToast instance property class
  
  
      var BvToast = /*#__PURE__*/function () {
        function BvToast(vm) {
          _classCallCheck(this, BvToast);
  
          // Assign the new properties to this instance
          assign(this, {
            _vm: vm,
            _root: vm.$root
          }); // Set these properties as read-only and non-enumerable
  
          defineProperties(this, {
            _vm: readonlyDescriptor(),
            _root: readonlyDescriptor()
          });
        } // --- Public Instance methods ---
        // Opens a user defined toast and returns immediately
  
  
        _createClass(BvToast, [{
          key: "toast",
          value: function toast(content) {
            var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
            if (!content || warnNotClient(PROP_NAME$3)) {
              /* istanbul ignore next */
              return;
            }
  
            makeToast(_objectSpread2({}, filterOptions$1(options), {
              toastContent: content
            }), this._vm);
          } // shows a `<b-toast>` component with the specified ID
  
        }, {
          key: "show",
          value: function show(id) {
            if (id) {
              this._root.$emit('bv::show::toast', id);
            }
          } // Hide a toast with specified ID, or if not ID all toasts
  
        }, {
          key: "hide",
          value: function hide() {
            var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
  
            this._root.$emit('bv::hide::toast', id);
          }
        }]);
  
        return BvToast;
      }(); // Add our instance mixin
  
  
      Vue.mixin({
        beforeCreate: function beforeCreate() {
          // Because we need access to `$root` for `$emits`, and VM for parenting,
          // we have to create a fresh instance of `BvToast` for each VM
          this[PROP_NAME_PRIV$1] = new BvToast(this);
        }
      }); // Define our read-only `$bvToast` instance property
      // Placed in an if just in case in HMR mode
      // eslint-disable-next-line no-prototype-builtins
  
      if (!Vue.prototype.hasOwnProperty(PROP_NAME$3)) {
        defineProperty(Vue.prototype, PROP_NAME$3, {
          get: function get() {
            /* istanbul ignore next */
            if (!this || !this[PROP_NAME_PRIV$1]) {
              warn("\"".concat(PROP_NAME$3, "\" must be accessed from a Vue instance \"this\" context."), 'BToast');
            }
  
            return this[PROP_NAME_PRIV$1];
          }
        });
      }
    };
  
    var BVToastPlugin = /*#__PURE__*/pluginFactory({
      plugins: {
        plugin: plugin$1
      }
    });
  
    var ToastPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BToast: BToast,
        BToaster: BToaster
      },
      // $bvToast injection
      plugins: {
        BVToastPlugin: BVToastPlugin
      }
    });
  
    var BV_TOOLTIP = '__BV_Tooltip__'; // Default trigger
  
    var DefaultTrigger$1 = 'hover focus'; // Valid event triggers
  
    var validTriggers$1 = {
      focus: true,
      hover: true,
      click: true,
      blur: true,
      manual: true
    }; // Directive modifier test regular expressions. Pre-compile for performance
  
    var htmlRE$1 = /^html$/i;
    var noninteractiveRE = /^noninteractive$/i;
    var noFadeRE$1 = /^nofade$/i;
    var placementRE$1 = /^(auto|top(left|right)?|bottom(left|right)?|left(top|bottom)?|right(top|bottom)?)$/i;
    var boundaryRE$1 = /^(window|viewport|scrollParent)$/i;
    var delayRE$1 = /^d\d+$/i;
    var delayShowRE$1 = /^ds\d+$/i;
    var delayHideRE$1 = /^dh\d+$/i;
    var offsetRE$1 = /^o-?\d+$/i;
    var variantRE$1 = /^v-.+$/i;
    var spacesRE$1 = /\s+/; // Build a Tooltip config based on bindings (if any)
    // Arguments and modifiers take precedence over passed value config object
  
    var parseBindings$1 = function parseBindings(bindings, vnode)
    /* istanbul ignore next: not easy to test */
    {
      // We start out with a basic config
      var NAME = 'BTooltip'; // Default config
  
      var config = {
        title: undefined,
        trigger: '',
        // Default set below if needed
        placement: 'top',
        fallbackPlacement: 'flip',
        container: false,
        // Default of body
        animation: true,
        offset: 0,
        id: null,
        html: false,
        interactive: true,
        disabled: false,
        delay: getComponentConfig(NAME, 'delay'),
        boundary: String(getComponentConfig(NAME, 'boundary')),
        boundaryPadding: parseInt(getComponentConfig(NAME, 'boundaryPadding'), 10) || 0,
        variant: getComponentConfig(NAME, 'variant'),
        customClass: getComponentConfig(NAME, 'customClass')
      }; // Process `bindings.value`
  
      if (isString(bindings.value) || isNumber(bindings.value)) {
        // Value is tooltip content (HTML optionally supported)
        config.title = bindings.value;
      } else if (isFunction(bindings.value)) {
        // Title generator function
        config.title = bindings.value;
      } else if (isPlainObject(bindings.value)) {
        // Value is config object, so merge
        config = _objectSpread2({}, config, {}, bindings.value);
      } // If title is not provided, try title attribute
  
  
      if (isUndefined(config.title)) {
        // Try attribute
        var data = vnode.data || {};
        config.title = data.attrs && !isUndefinedOrNull(data.attrs.title) ? data.attrs.title : undefined;
      } // Normalize delay
  
  
      if (!isPlainObject(config.delay)) {
        config.delay = {
          show: parseInt(config.delay, 10) || 0,
          hide: parseInt(config.delay, 10) || 0
        };
      } // If argument, assume element ID of container element
  
  
      if (bindings.arg) {
        // Element ID specified as arg
        // We must prepend '#' to become a CSS selector
        config.container = "#".concat(bindings.arg);
      } // Process modifiers
  
  
      keys(bindings.modifiers).forEach(function (mod) {
        if (htmlRE$1.test(mod)) {
          // Title allows HTML
          config.html = true;
        } else if (noninteractiveRE.test(mod)) {
          // Noninteractive
          config.interactive = false;
        } else if (noFadeRE$1.test(mod)) {
          // No animation
          config.animation = false;
        } else if (placementRE$1.test(mod)) {
          // Placement of tooltip
          config.placement = mod;
        } else if (boundaryRE$1.test(mod)) {
          // Boundary of tooltip
          mod = mod === 'scrollparent' ? 'scrollParent' : mod;
          config.boundary = mod;
        } else if (delayRE$1.test(mod)) {
          // Delay value
          var delay = parseInt(mod.slice(1), 10) || 0;
          config.delay.show = delay;
          config.delay.hide = delay;
        } else if (delayShowRE$1.test(mod)) {
          // Delay show value
          config.delay.show = parseInt(mod.slice(2), 10) || 0;
        } else if (delayHideRE$1.test(mod)) {
          // Delay hide value
          config.delay.hide = parseInt(mod.slice(2), 10) || 0;
        } else if (offsetRE$1.test(mod)) {
          // Offset value, negative allowed
          config.offset = parseInt(mod.slice(1), 10) || 0;
        } else if (variantRE$1.test(mod)) {
          // Variant
          config.variant = mod.slice(2) || null;
        }
      }); // Special handling of event trigger modifiers trigger is
      // a space separated list
  
      var selectedTriggers = {}; // Parse current config object trigger
  
      concat(config.trigger || '').filter(identity).join(' ').trim().toLowerCase().split(spacesRE$1).forEach(function (trigger) {
        if (validTriggers$1[trigger]) {
          selectedTriggers[trigger] = true;
        }
      }); // Parse modifiers for triggers
  
      keys(bindings.modifiers).forEach(function (mod) {
        mod = mod.toLowerCase();
  
        if (validTriggers$1[mod]) {
          // If modifier is a valid trigger
          selectedTriggers[mod] = true;
        }
      }); // Sanitize triggers
  
      config.trigger = keys(selectedTriggers).join(' ');
  
      if (config.trigger === 'blur') {
        // Blur by itself is useless, so convert it to 'focus'
        config.trigger = 'focus';
      }
  
      if (!config.trigger) {
        // Use default trigger
        config.trigger = DefaultTrigger$1;
      } // Return the config
  
  
      return config;
    }; // Add/update Tooltip on our element
  
  
    var applyTooltip = function applyTooltip(el, bindings, vnode) {
      if (!isBrowser) {
        /* istanbul ignore next */
        return;
      }
  
      var config = parseBindings$1(bindings, vnode);
  
      if (!el[BV_TOOLTIP]) {
        var $parent = vnode.context;
        el[BV_TOOLTIP] = new BVTooltip({
          parent: $parent,
          // Add the parent's scoped style attribute data
          _scopeId: getScopeId($parent, undefined)
        });
        el[BV_TOOLTIP].__bv_prev_data__ = {};
        el[BV_TOOLTIP].$on('show', function ()
        /* istanbul ignore next: for now */
        {
          // Before showing the tooltip, we update the title if it is a function
          if (isFunction(config.title)) {
            el[BV_TOOLTIP].updateData({
              title: config.title(el)
            });
          }
        });
      }
  
      var data = {
        title: config.title,
        triggers: config.trigger,
        placement: config.placement,
        fallbackPlacement: config.fallbackPlacement,
        variant: config.variant,
        customClass: config.customClass,
        container: config.container,
        boundary: config.boundary,
        delay: config.delay,
        offset: config.offset,
        noFade: !config.animation,
        id: config.id,
        interactive: config.interactive,
        disabled: config.disabled,
        html: config.html
      };
      var oldData = el[BV_TOOLTIP].__bv_prev_data__;
      el[BV_TOOLTIP].__bv_prev_data__ = data;
  
      if (!looseEqual(data, oldData)) {
        // We only update the instance if data has changed
        var newData = {
          target: el
        };
        keys(data).forEach(function (prop) {
          // We only pass data properties that have changed
          if (data[prop] !== oldData[prop]) {
            // if title is a function, we execute it here
            newData[prop] = prop === 'title' && isFunction(data[prop]) ? data[prop](el) : data[prop];
          }
        });
        el[BV_TOOLTIP].updateData(newData);
      }
    }; // Remove Tooltip on our element
  
  
    var removeTooltip = function removeTooltip(el) {
      if (el[BV_TOOLTIP]) {
        el[BV_TOOLTIP].$destroy();
        el[BV_TOOLTIP] = null;
      }
  
      delete el[BV_TOOLTIP];
    }; // Export our directive
  
  
    var VBTooltip = {
      bind: function bind(el, bindings, vnode) {
        applyTooltip(el, bindings, vnode);
      },
      // We use `componentUpdated` here instead of `update`, as the former
      // waits until the containing component and children have finished updating
      componentUpdated: function componentUpdated(el, bindings, vnode) {
        // Performed in a `$nextTick()` to prevent render update loops
        vnode.context.$nextTick(function () {
          applyTooltip(el, bindings, vnode);
        });
      },
      unbind: function unbind(el) {
        removeTooltip(el);
      }
    };
  
    var VBTooltipPlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBTooltip: VBTooltip
      }
    });
  
    var TooltipPlugin = /*#__PURE__*/pluginFactory({
      components: {
        BTooltip: BTooltip
      },
      plugins: {
        VBTooltipPlugin: VBTooltipPlugin
      }
    });
  
    var componentsPlugin = /*#__PURE__*/pluginFactory({
      plugins: {
        AlertPlugin: AlertPlugin,
        BadgePlugin: BadgePlugin,
        BreadcrumbPlugin: BreadcrumbPlugin,
        ButtonPlugin: ButtonPlugin,
        ButtonGroupPlugin: ButtonGroupPlugin,
        ButtonToolbarPlugin: ButtonToolbarPlugin,
        CalendarPlugin: CalendarPlugin,
        CardPlugin: CardPlugin,
        CarouselPlugin: CarouselPlugin,
        CollapsePlugin: CollapsePlugin,
        DropdownPlugin: DropdownPlugin,
        EmbedPlugin: EmbedPlugin,
        FormPlugin: FormPlugin,
        FormCheckboxPlugin: FormCheckboxPlugin,
        FormDatepickerPlugin: FormDatepickerPlugin,
        FormFilePlugin: FormFilePlugin,
        FormGroupPlugin: FormGroupPlugin,
        FormInputPlugin: FormInputPlugin,
        FormRadioPlugin: FormRadioPlugin,
        FormSelectPlugin: FormSelectPlugin,
        FormSpinbuttonPlugin: FormSpinbuttonPlugin,
        FormTagsPlugin: FormTagsPlugin,
        FormTextareaPlugin: FormTextareaPlugin,
        FormTimepickerPlugin: FormTimepickerPlugin,
        ImagePlugin: ImagePlugin,
        InputGroupPlugin: InputGroupPlugin,
        JumbotronPlugin: JumbotronPlugin,
        LayoutPlugin: LayoutPlugin,
        LinkPlugin: LinkPlugin,
        ListGroupPlugin: ListGroupPlugin,
        MediaPlugin: MediaPlugin,
        ModalPlugin: ModalPlugin,
        NavPlugin: NavPlugin,
        NavbarPlugin: NavbarPlugin,
        PaginationPlugin: PaginationPlugin,
        PaginationNavPlugin: PaginationNavPlugin,
        PopoverPlugin: PopoverPlugin,
        ProgressPlugin: ProgressPlugin,
        SpinnerPlugin: SpinnerPlugin,
        TablePlugin: TablePlugin,
        TabsPlugin: TabsPlugin,
        TimePlugin: TimePlugin,
        ToastPlugin: ToastPlugin,
        TooltipPlugin: TooltipPlugin
      }
    });
  
    var VBHoverPlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBHover: VBHover
      }
    });
  
    var VBModalPlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBModal: VBModal
      }
    });
  
    /*
     * Constants / Defaults
     */
  
    var NAME$G = 'v-b-scrollspy';
    var ACTIVATE_EVENT = 'bv::scrollspy::activate';
    var Default = {
      element: 'body',
      offset: 10,
      method: 'auto',
      throttle: 75
    };
    var DefaultType = {
      element: '(string|element|component)',
      offset: 'number',
      method: 'string',
      throttle: 'number'
    };
    var ClassName = {
      DROPDOWN_ITEM: 'dropdown-item',
      ACTIVE: 'active'
    };
    var Selector$2 = {
      ACTIVE: '.active',
      NAV_LIST_GROUP: '.nav, .list-group',
      NAV_LINKS: '.nav-link',
      NAV_ITEMS: '.nav-item',
      LIST_ITEMS: '.list-group-item',
      DROPDOWN: '.dropdown, .dropup',
      DROPDOWN_ITEMS: '.dropdown-item',
      DROPDOWN_TOGGLE: '.dropdown-toggle'
    };
    var OffsetMethod = {
      OFFSET: 'offset',
      POSITION: 'position'
    }; // HREFs must end with a hash followed by at least one non-hash character.
    // HREFs in the links are assumed to point to non-external links.
    // Comparison to the current page base URL is not performed!
  
    var HREF_REGEX = /^.*(#[^#]+)$/; // Transition Events
  
    var TransitionEndEvents$1 = ['webkitTransitionEnd', 'transitionend', 'otransitionend', 'oTransitionEnd'];
    /*
     * Utility Methods
     */
    // Better var type detection
  
    var toType$1 = function toType(obj)
    /* istanbul ignore next: not easy to test */
    {
      return toString(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
    }; // Check config properties for expected types
  
  
    var typeCheckConfig = function typeCheckConfig(componentName, config, configTypes)
    /* istanbul ignore next: not easy to test */
    {
      for (var property in configTypes) {
        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
          var expectedTypes = configTypes[property];
          var value = config[property];
          var valueType = value && isElement(value) ? 'element' : toType$1(value); // handle Vue instances
  
          valueType = value && value._isVue ? 'component' : valueType;
  
          if (!new RegExp(expectedTypes).test(valueType)) {
            /* istanbul ignore next */
            warn("".concat(componentName, ": Option \"").concat(property, "\" provided type \"").concat(valueType, "\" but expected type \"").concat(expectedTypes, "\""));
          }
        }
      }
    };
    /*
     * ------------------------------------------------------------------------
     * Class Definition
     * ------------------------------------------------------------------------
     */
  
    /* istanbul ignore next: not easy to test */
  
  
    var ScrollSpy
    /* istanbul ignore next: not easy to test */
    = /*#__PURE__*/function () {
      function ScrollSpy(element, config, $root) {
        _classCallCheck(this, ScrollSpy);
  
        // The element we activate links in
        this.$el = element;
        this.$scroller = null;
        this.$selector = [Selector$2.NAV_LINKS, Selector$2.LIST_ITEMS, Selector$2.DROPDOWN_ITEMS].join(',');
        this.$offsets = [];
        this.$targets = [];
        this.$activeTarget = null;
        this.$scrollHeight = 0;
        this.$resizeTimeout = null;
        this.$obs_scroller = null;
        this.$obs_targets = null;
        this.$root = $root || null;
        this.$config = null;
        this.updateConfig(config);
      }
  
      _createClass(ScrollSpy, [{
        key: "updateConfig",
        value: function updateConfig(config, $root) {
          if (this.$scroller) {
            // Just in case out scroll element has changed
            this.unlisten();
            this.$scroller = null;
          }
  
          var cfg = _objectSpread2({}, this.constructor.Default, {}, config);
  
          if ($root) {
            this.$root = $root;
          }
  
          typeCheckConfig(this.constructor.Name, cfg, this.constructor.DefaultType);
          this.$config = cfg;
  
          if (this.$root) {
            var self = this;
            this.$root.$nextTick(function () {
              self.listen();
            });
          } else {
            this.listen();
          }
        }
      }, {
        key: "dispose",
        value: function dispose() {
          this.unlisten();
          clearTimeout(this.$resizeTimeout);
          this.$resizeTimeout = null;
          this.$el = null;
          this.$config = null;
          this.$scroller = null;
          this.$selector = null;
          this.$offsets = null;
          this.$targets = null;
          this.$activeTarget = null;
          this.$scrollHeight = null;
        }
      }, {
        key: "listen",
        value: function listen() {
          var _this = this;
  
          var scroller = this.getScroller();
  
          if (scroller && scroller.tagName !== 'BODY') {
            eventOn(scroller, 'scroll', this, EVENT_OPTIONS_NO_CAPTURE);
          }
  
          eventOn(window, 'scroll', this, EVENT_OPTIONS_NO_CAPTURE);
          eventOn(window, 'resize', this, EVENT_OPTIONS_NO_CAPTURE);
          eventOn(window, 'orientationchange', this, EVENT_OPTIONS_NO_CAPTURE);
          TransitionEndEvents$1.forEach(function (evtName) {
            eventOn(window, evtName, _this, EVENT_OPTIONS_NO_CAPTURE);
          });
          this.setObservers(true); // Schedule a refresh
  
          this.handleEvent('refresh');
        }
      }, {
        key: "unlisten",
        value: function unlisten() {
          var _this2 = this;
  
          var scroller = this.getScroller();
          this.setObservers(false);
  
          if (scroller && scroller.tagName !== 'BODY') {
            eventOff(scroller, 'scroll', this, EVENT_OPTIONS_NO_CAPTURE);
          }
  
          eventOff(window, 'scroll', this, EVENT_OPTIONS_NO_CAPTURE);
          eventOff(window, 'resize', this, EVENT_OPTIONS_NO_CAPTURE);
          eventOff(window, 'orientationchange', this, EVENT_OPTIONS_NO_CAPTURE);
          TransitionEndEvents$1.forEach(function (evtName) {
            eventOff(window, evtName, _this2, EVENT_OPTIONS_NO_CAPTURE);
          });
        }
      }, {
        key: "setObservers",
        value: function setObservers(on) {
          var _this3 = this;
  
          // We observe both the scroller for content changes, and the target links
          if (this.$obs_scroller) {
            this.$obs_scroller.disconnect();
            this.$obs_scroller = null;
          }
  
          if (this.$obs_targets) {
            this.$obs_targets.disconnect();
            this.$obs_targets = null;
          }
  
          if (on) {
            this.$obs_targets = observeDom(this.$el, function () {
              _this3.handleEvent('mutation');
            }, {
              subtree: true,
              childList: true,
              attributes: true,
              attributeFilter: ['href']
            });
            this.$obs_scroller = observeDom(this.getScroller(), function () {
              _this3.handleEvent('mutation');
            }, {
              subtree: true,
              childList: true,
              characterData: true,
              attributes: true,
              attributeFilter: ['id', 'style', 'class']
            });
          }
        } // General event handler
  
      }, {
        key: "handleEvent",
        value: function handleEvent(evt) {
          var type = isString(evt) ? evt : evt.type;
          var self = this;
  
          var resizeThrottle = function resizeThrottle() {
            if (!self.$resizeTimeout) {
              self.$resizeTimeout = setTimeout(function () {
                self.refresh();
                self.process();
                self.$resizeTimeout = null;
              }, self.$config.throttle);
            }
          };
  
          if (type === 'scroll') {
            if (!this.$obs_scroller) {
              // Just in case we are added to the DOM before the scroll target is
              // We re-instantiate our listeners, just in case
              this.listen();
            }
  
            this.process();
          } else if (/(resize|orientationchange|mutation|refresh)/.test(type)) {
            // Postpone these events by throttle time
            resizeThrottle();
          }
        } // Refresh the list of target links on the element we are applied to
  
      }, {
        key: "refresh",
        value: function refresh() {
          var _this4 = this;
  
          var scroller = this.getScroller();
  
          if (!scroller) {
            return;
          }
  
          var autoMethod = scroller !== scroller.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
          var method = this.$config.method === 'auto' ? autoMethod : this.$config.method;
          var methodFn = method === OffsetMethod.POSITION ? position : offset;
          var offsetBase = method === OffsetMethod.POSITION ? this.getScrollTop() : 0;
          this.$offsets = [];
          this.$targets = [];
          this.$scrollHeight = this.getScrollHeight(); // Find all the unique link HREFs that we will control
  
          selectAll(this.$selector, this.$el) // Get HREF value
          .map(function (link) {
            return getAttr(link, 'href');
          }) // Filter out HREFs that do not match our RegExp
          .filter(function (href) {
            return href && HREF_REGEX.test(href || '');
          }) // Find all elements with ID that match HREF hash
          .map(function (href) {
            // Convert HREF into an ID (including # at beginning)
            var id = href.replace(HREF_REGEX, '$1').trim();
  
            if (!id) {
              return null;
            } // Find the element with the ID specified by id
  
  
            var el = select(id, scroller);
  
            if (el && isVisible(el)) {
              return {
                offset: parseInt(methodFn(el).top, 10) + offsetBase,
                target: id
              };
            }
  
            return null;
          }).filter(Boolean) // Sort them by their offsets (smallest first)
          .sort(function (a, b) {
            return a.offset - b.offset;
          }) // record only unique targets/offsets
          .reduce(function (memo, item) {
            if (!memo[item.target]) {
              _this4.$offsets.push(item.offset);
  
              _this4.$targets.push(item.target);
  
              memo[item.target] = true;
            }
  
            return memo;
          }, {}); // Return this for easy chaining
  
          return this;
        } // Handle activating/clearing
  
      }, {
        key: "process",
        value: function process() {
          var scrollTop = this.getScrollTop() + this.$config.offset;
          var scrollHeight = this.getScrollHeight();
          var maxScroll = this.$config.offset + scrollHeight - this.getOffsetHeight();
  
          if (this.$scrollHeight !== scrollHeight) {
            this.refresh();
          }
  
          if (scrollTop >= maxScroll) {
            var target = this.$targets[this.$targets.length - 1];
  
            if (this.$activeTarget !== target) {
              this.activate(target);
            }
  
            return;
          }
  
          if (this.$activeTarget && scrollTop < this.$offsets[0] && this.$offsets[0] > 0) {
            this.$activeTarget = null;
            this.clear();
            return;
          }
  
          for (var i = this.$offsets.length; i--;) {
            var isActiveTarget = this.$activeTarget !== this.$targets[i] && scrollTop >= this.$offsets[i] && (isUndefined(this.$offsets[i + 1]) || scrollTop < this.$offsets[i + 1]);
  
            if (isActiveTarget) {
              this.activate(this.$targets[i]);
            }
          }
        }
      }, {
        key: "getScroller",
        value: function getScroller() {
          if (this.$scroller) {
            return this.$scroller;
          }
  
          var scroller = this.$config.element;
  
          if (!scroller) {
            return null;
          } else if (isElement(scroller.$el)) {
            scroller = scroller.$el;
          } else if (isString(scroller)) {
            scroller = select(scroller);
          }
  
          if (!scroller) {
            return null;
          }
  
          this.$scroller = scroller.tagName === 'BODY' ? window : scroller;
          return this.$scroller;
        }
      }, {
        key: "getScrollTop",
        value: function getScrollTop() {
          var scroller = this.getScroller();
          return scroller === window ? scroller.pageYOffset : scroller.scrollTop;
        }
      }, {
        key: "getScrollHeight",
        value: function getScrollHeight() {
          return this.getScroller().scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
        }
      }, {
        key: "getOffsetHeight",
        value: function getOffsetHeight() {
          var scroller = this.getScroller();
          return scroller === window ? window.innerHeight : getBCR(scroller).height;
        }
      }, {
        key: "activate",
        value: function activate(target) {
          var _this5 = this;
  
          this.$activeTarget = target;
          this.clear(); // Grab the list of target links (<a href="{$target}">)
  
          var links = selectAll(this.$selector // Split out the base selectors
          .split(',') // Map to a selector that matches links with HREF ending in the ID (including '#')
          .map(function (selector) {
            return "".concat(selector, "[href$=\"").concat(target, "\"]");
          }) // Join back into a single selector string
          .join(','), this.$el);
          links.forEach(function (link) {
            if (hasClass(link, ClassName.DROPDOWN_ITEM)) {
              // This is a dropdown item, so find the .dropdown-toggle and set its state
              var dropdown = closest(Selector$2.DROPDOWN, link);
  
              if (dropdown) {
                _this5.setActiveState(select(Selector$2.DROPDOWN_TOGGLE, dropdown), true);
              } // Also set this link's state
  
  
              _this5.setActiveState(link, true);
            } else {
              // Set triggered link as active
              _this5.setActiveState(link, true);
  
              if (matches(link.parentElement, Selector$2.NAV_ITEMS)) {
                // Handle nav-link inside nav-item, and set nav-item active
                _this5.setActiveState(link.parentElement, true);
              } // Set triggered links parents as active
              // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
  
  
              var el = link;
  
              while (el) {
                el = closest(Selector$2.NAV_LIST_GROUP, el);
                var sibling = el ? el.previousElementSibling : null;
  
                if (sibling && matches(sibling, "".concat(Selector$2.NAV_LINKS, ", ").concat(Selector$2.LIST_ITEMS))) {
                  _this5.setActiveState(sibling, true);
                } // Handle special case where nav-link is inside a nav-item
  
  
                if (sibling && matches(sibling, Selector$2.NAV_ITEMS)) {
                  _this5.setActiveState(select(Selector$2.NAV_LINKS, sibling), true); // Add active state to nav-item as well
  
  
                  _this5.setActiveState(sibling, true);
                }
              }
            }
          }); // Signal event to via $root, passing ID of activated target and reference to array of links
  
          if (links && links.length > 0 && this.$root) {
            this.$root.$emit(ACTIVATE_EVENT, target, links);
          }
        }
      }, {
        key: "clear",
        value: function clear() {
          var _this6 = this;
  
          selectAll("".concat(this.$selector, ", ").concat(Selector$2.NAV_ITEMS), this.$el).filter(function (el) {
            return hasClass(el, ClassName.ACTIVE);
          }).forEach(function (el) {
            return _this6.setActiveState(el, false);
          });
        }
      }, {
        key: "setActiveState",
        value: function setActiveState(el, active) {
          if (!el) {
            return;
          }
  
          if (active) {
            addClass(el, ClassName.ACTIVE);
          } else {
            removeClass(el, ClassName.ACTIVE);
          }
        }
      }], [{
        key: "Name",
        get: function get() {
          return NAME$G;
        }
      }, {
        key: "Default",
        get: function get() {
          return Default;
        }
      }, {
        key: "DefaultType",
        get: function get() {
          return DefaultType;
        }
      }]);
  
      return ScrollSpy;
    }();
  
    var BV_SCROLLSPY = '__BV_ScrollSpy__'; // Pre-compiled regular expressions
  
    var onlyDigitsRE = /^\d+$/;
    var offsetRE$2 = /^(auto|position|offset)$/; // Build a ScrollSpy config based on bindings (if any)
    // Arguments and modifiers take precedence over passed value config object
  
    /* istanbul ignore next: not easy to test */
  
    var parseBindings$2 = function parseBindings(bindings)
    /* istanbul ignore next: not easy to test */
    {
      var config = {}; // If argument, assume element ID
  
      if (bindings.arg) {
        // Element ID specified as arg
        // We must prepend '#' to become a CSS selector
        config.element = "#".concat(bindings.arg);
      } // Process modifiers
  
  
      keys(bindings.modifiers).forEach(function (mod) {
        if (onlyDigitsRE.test(mod)) {
          // Offset value
          config.offset = parseInt(mod, 10);
        } else if (offsetRE$2.test(mod)) {
          // Offset method
          config.method = mod;
        }
      }); // Process value
  
      if (isString(bindings.value)) {
        // Value is a CSS ID or selector
        config.element = bindings.value;
      } else if (isNumber(bindings.value)) {
        // Value is offset
        config.offset = Math.round(bindings.value);
      } else if (isObject(bindings.value)) {
        // Value is config object
        // Filter the object based on our supported config options
        keys(bindings.value).filter(function (k) {
          return !!ScrollSpy.DefaultType[k];
        }).forEach(function (k) {
          config[k] = bindings.value[k];
        });
      }
  
      return config;
    }; // Add or update ScrollSpy on our element
  
  
    var applyScrollspy = function applyScrollspy(el, bindings, vnode)
    /* istanbul ignore next: not easy to test */
    {
      if (!isBrowser) {
        /* istanbul ignore next */
        return;
      }
  
      var config = parseBindings$2(bindings);
  
      if (el[BV_SCROLLSPY]) {
        el[BV_SCROLLSPY].updateConfig(config, vnode.context.$root);
      } else {
        el[BV_SCROLLSPY] = new ScrollSpy(el, config, vnode.context.$root);
      }
    }; // Remove ScrollSpy on our element
  
    /* istanbul ignore next: not easy to test */
  
  
    var removeScrollspy = function removeScrollspy(el)
    /* istanbul ignore next: not easy to test */
    {
      if (el[BV_SCROLLSPY]) {
        el[BV_SCROLLSPY].dispose();
        el[BV_SCROLLSPY] = null;
        delete el[BV_SCROLLSPY];
      }
    };
    /*
     * Export our directive
     */
  
  
    var VBScrollspy = {
      bind: function bind(el, bindings, vnode)
      /* istanbul ignore next: not easy to test */
      {
        applyScrollspy(el, bindings, vnode);
      },
      inserted: function inserted(el, bindings, vnode)
      /* istanbul ignore next: not easy to test */
      {
        applyScrollspy(el, bindings, vnode);
      },
      update: function update(el, bindings, vnode)
      /* istanbul ignore next: not easy to test */
      {
        if (bindings.value !== bindings.oldValue) {
          applyScrollspy(el, bindings, vnode);
        }
      },
      componentUpdated: function componentUpdated(el, bindings, vnode)
      /* istanbul ignore next: not easy to test */
      {
        if (bindings.value !== bindings.oldValue) {
          applyScrollspy(el, bindings, vnode);
        }
      },
      unbind: function unbind(el)
      /* istanbul ignore next: not easy to test */
      {
        removeScrollspy(el);
      }
    };
  
    var VBScrollspyPlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBScrollspy: VBScrollspy
      }
    });
  
    var VBTogglePlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBToggle: VBToggle
      }
    });
  
    var VBVisiblePlugin = /*#__PURE__*/pluginFactory({
      directives: {
        VBVisible: VBVisible
      }
    });
  
    var directivesPlugin = /*#__PURE__*/pluginFactory({
      plugins: {
        VBHoverPlugin: VBHoverPlugin,
        VBModalPlugin: VBModalPlugin,
        VBPopoverPlugin: VBPopoverPlugin,
        VBScrollspyPlugin: VBScrollspyPlugin,
        VBTogglePlugin: VBTogglePlugin,
        VBTooltipPlugin: VBTooltipPlugin,
        VBVisiblePlugin: VBVisiblePlugin
      }
    });
  
    var RX_ICON_PREFIX = /^BIcon/; // Helper BIcon component
    // Requires the requested icon component to be installed
  
    var BIcon = /*#__PURE__*/Vue.extend({
      name: 'BIcon',
      functional: true,
      props: _objectSpread2({
        icon: {
          type: String,
          default: null
        }
      }, commonIconProps, {
        stacked: {
          type: Boolean,
          default: false
        }
      }),
      render: function render(h, _ref) {
        var data = _ref.data,
            props = _ref.props,
            parent = _ref.parent;
        var icon = pascalCase(trim(props.icon || '')).replace(RX_ICON_PREFIX, '');
        var iconName = "BIcon".concat(icon); // If parent context exists, we check to see if the icon has been registered
        // Either locally in the parent component, or globally at the `$root` level
        // If not registered, we render a blank icon
  
        var components = ((parent || {}).$options || {}).components;
        var componentRefOrName = icon && components ? components[iconName] || BIconBlank : icon ? iconName : BIconBlank;
        return h(componentRefOrName, a(data, {
          props: _objectSpread2({}, props, {
            icon: null
          })
        }));
      }
    });
  
    var NAME$H = 'BootstrapVue'; // --- BootstrapVue installer ---
  
    var install = /*#__PURE__*/installFactory({
      plugins: {
        componentsPlugin: componentsPlugin,
        directivesPlugin: directivesPlugin
      }
    }); // --- BootstrapVue plugin ---
  
    var BootstrapVue = /*#__PURE__*/{
      install: install,
      NAME: NAME$H
    }; // --- Named exports for BvConfigPlugin ---
  
    // Main entry point for the browser build
  
    vueUse(BootstrapVue);
  
    return BootstrapVue;
  
  })));
  //# sourceMappingURL=bootstrap-vue.js.map
  