![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/vreg/node_modules/bootstrap-vue/dist/ |
/*! * BootstrapVue 2.21.2 * * @link https://bootstrap-vue.org * @source https://github.com/bootstrap-vue/bootstrap-vue * @copyright (c) 2016-2021 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 = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrapVue = factory(global.Vue)); }(this, (function (Vue) { 'use strict'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var Vue__default = /*#__PURE__*/_interopDefaultLegacy(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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } 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) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) 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 _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } 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 COMPONENT_UID_KEY = '_uid'; var HAS_WINDOW_SUPPORT = typeof window !== 'undefined'; var HAS_DOCUMENT_SUPPORT = typeof document !== 'undefined'; var HAS_NAVIGATOR_SUPPORT = typeof navigator !== 'undefined'; var HAS_PROMISE_SUPPORT = typeof Promise !== 'undefined'; /* istanbul ignore next: JSDOM always returns false */ var HAS_MUTATION_OBSERVER_SUPPORT = typeof MutationObserver !== 'undefined' || typeof WebKitMutationObserver !== 'undefined' || typeof MozMutationObserver !== 'undefined'; var IS_BROWSER = HAS_WINDOW_SUPPORT && HAS_DOCUMENT_SUPPORT && HAS_NAVIGATOR_SUPPORT; var WINDOW = HAS_WINDOW_SUPPORT ? window : {}; var DOCUMENT = HAS_DOCUMENT_SUPPORT ? document : {}; var NAVIGATOR = HAS_NAVIGATOR_SUPPORT ? navigator : {}; var USER_AGENT = (NAVIGATOR.userAgent || '').toLowerCase(); var IS_JSDOM = USER_AGENT.indexOf('jsdom') > 0; var IS_IE = /msie|trident/.test(USER_AGENT); // Determine if the browser supports the option passive for events var HAS_PASSIVE_EVENT_SUPPORT = function () { var passiveEventSupported = false; if (IS_BROWSER) { try { var options = { // This function will be called when the browser // attempts to access the passive property get passive() { /* istanbul ignore next: will never be called in JSDOM */ passiveEventSupported = true; } }; WINDOW.addEventListener('test', options, options); WINDOW.removeEventListener('test', options, options); } catch (_unused) { /* istanbul ignore next: will never be called in JSDOM */ passiveEventSupported = false; } } return passiveEventSupported; }(); var HAS_TOUCH_SUPPORT = IS_BROWSER && ('ontouchstart' in DOCUMENT.documentElement || NAVIGATOR.maxTouchPoints > 0); var HAS_POINTER_EVENT_SUPPORT = IS_BROWSER && Boolean(WINDOW.PointerEvent || WINDOW.MSPointerEvent); /* istanbul ignore next: JSDOM only checks for 'IntersectionObserver' */ var HAS_INTERACTION_OBSERVER_SUPPORT = IS_BROWSER && '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; var NAME = 'BvConfig'; var PROP_NAME = '$bvConfig'; var DEFAULT_BREAKPOINT = ['xs', 'sm', 'md', 'lg', 'xl']; // --- General --- var RX_ARRAY_NOTATION = /\[(\d+)]/g; var RX_BV_PREFIX = /^(BV?)/; var RX_DIGITS = /^\d+$/; var RX_EXTENSION = /^\..+/; var RX_HASH = /^#/; var RX_HASH_ID = /^#[A-Za-z]+[\w\-:.]*$/; var RX_HTML_TAGS = /(<([^>]+)>)/gi; var RX_HYPHENATE = /\B([A-Z])/g; var RX_LOWER_UPPER = /([a-z])([A-Z])/g; var RX_NUMBER = /^[0-9]*\.?[0-9]+$/; var RX_PLUS = /\+/g; var RX_REGEXP_REPLACE = /[-/\\^$*+?.()|[\]{}]/g; var RX_SPACES = /[\s\uFEFF\xA0]+/g; var RX_SPACE_SPLIT = /\s+/; var RX_STAR = /\/\*$/; var RX_START_SPACE_WORD = /(\s|^)(\w)/g; var RX_TRIM_LEFT = /^\s+/; var RX_UNDERSCORE = /_/g; var RX_UN_KEBAB = /-(\w)/g; // --- Date --- // Loose YYYY-MM-DD matching, ignores any appended time inforation // Matches '1999-12-20', '1999-1-1', '1999-01-20T22:51:49.118Z', '1999-01-02 13:00:00' var RX_DATE = /^\d+-\d\d?-\d\d?(?:\s|T|$)/; // Used to split off the date parts of the YYYY-MM-DD string var RX_DATE_SPLIT = /-|\s|T/; // Time string RegEx (optional seconds) var RX_TIME = /^([0-1]?[0-9]|2[0-3]):[0-5]?[0-9](:[0-5]?[0-9])?$/; // --- URL --- // HREFs must end with a hash followed by at least one non-hash character var RX_HREF = /^.*(#[^#]+)$/; var RX_ENCODED_COMMA = /%2C/g; var RX_ENCODE_REVERSE = /[!'()*]/g; var RX_QUERY_START = /^(\?|#|&)/; // --- Aspect --- var RX_ASPECT = /^\d+(\.\d*)?[/:]\d+(\.\d*)?$/; var RX_ASPECT_SEPARATOR = /[/:]/; // --- Grid --- var RX_COL_CLASS = /^col-/; // --- Icon --- var RX_ICON_PREFIX = /^BIcon/; // --- Locale --- var RX_STRIP_LOCALE_MODS = /-u-.+/; /* istanbul ignore next */ var Element = HAS_WINDOW_SUPPORT ? WINDOW.Element : /*#__PURE__*/function (_Object) { _inherits(Element, _Object); var _super = _createSuper(Element); function Element() { _classCallCheck(this, Element); return _super.apply(this, arguments); } return Element; }( /*#__PURE__*/_wrapNativeSuper(Object)); /* istanbul ignore next */ var HTMLElement = HAS_WINDOW_SUPPORT ? WINDOW.HTMLElement : /*#__PURE__*/function (_Element) { _inherits(HTMLElement, _Element); var _super2 = _createSuper(HTMLElement); function HTMLElement() { _classCallCheck(this, HTMLElement); return _super2.apply(this, arguments); } return HTMLElement; }(Element); /* istanbul ignore next */ var SVGElement = HAS_WINDOW_SUPPORT ? WINDOW.SVGElement : /*#__PURE__*/function (_Element2) { _inherits(SVGElement, _Element2); var _super3 = _createSuper(SVGElement); function SVGElement() { _classCallCheck(this, SVGElement); return _super3.apply(this, arguments); } return SVGElement; }(Element); /* istanbul ignore next */ var File = HAS_WINDOW_SUPPORT ? WINDOW.File : /*#__PURE__*/function (_Object2) { _inherits(File, _Object2); var _super4 = _createSuper(File); function File() { _classCallCheck(this, File); return _super4.apply(this, arguments); } return File; }( /*#__PURE__*/_wrapNativeSuper(Object)); var toType = function toType(value) { return _typeof(value); }; var toRawType = function toRawType(value) { return Object.prototype.toString.call(value).slice(8, -1); }; var isUndefined = function isUndefined(value) { return value === undefined; }; var isNull = function isNull(value) { return value === null; }; var isUndefinedOrNull = function isUndefinedOrNull(value) { return isUndefined(value) || isNull(value); }; var isFunction = function isFunction(value) { return toType(value) === 'function'; }; var isBoolean = function isBoolean(value) { return toType(value) === 'boolean'; }; var isString = function isString(value) { return toType(value) === 'string'; }; var isNumber = function isNumber(value) { return toType(value) === 'number'; }; var isNumeric = function isNumeric(value) { return RX_NUMBER.test(String(value)); }; var isArray = function isArray(value) { return Array.isArray(value); }; // 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]'; }; var isDate = function isDate(value) { return value instanceof Date; }; var isEvent = function isEvent(value) { return value instanceof Event; }; var isFile = function isFile(value) { return value instanceof File; }; var isRegExp = function isRegExp(value) { return toRawType(value) === 'RegExp'; }; var isPromise = function isPromise(value) { return !isUndefinedOrNull(value) && isFunction(value.then) && isFunction(value.catch); }; 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, descriptor) { return Object.defineProperty(obj, prop, descriptor); }; 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 --- // Shallow copy an object var clone = function clone(obj) { return _objectSpread2({}, obj); }; // Return a shallow copy of object with the specified properties only // See: https://gist.github.com/bisubus/2da8af7e801ffd813fab7ac221aa7afc var pick = function pick(obj, props) { return keys(obj).filter(function (key) { return props.indexOf(key) !== -1; }).reduce(function (result, key) { return _objectSpread2(_objectSpread2({}, result), {}, _defineProperty({}, key, obj[key])); }, {}); }; // Return a shallow copy of object with the specified properties omitted // See: 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(_objectSpread2({}, result), {}, _defineProperty({}, key, obj[key])); }, {}); }; // Merges two object deeply together // See: https://gist.github.com/Salakar/1d7137de9cb8b704e48a var mergeDeep = function mergeDeep(target, source) { if (isObject(target) && isObject(source)) { keys(source).forEach(function (key) { if (isObject(source[key])) { if (!target[key] || !isObject(target[key])) { target[key] = source[key]; } mergeDeep(target[key], source[key]); } else { assign(target, _defineProperty({}, key, source[key])); } }); } return target; }; // Returns a shallow copy of the object with keys in sorted order var sortKeys = function sortKeys(obj) { return keys(obj).sort().reduce(function (result, key) { return _objectSpread2(_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 }; }; 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(_objectSpread2({}, result), {}, _defineProperty({}, key, cloneDeep(obj[key], obj[key]))); }, {}); } return defaultValue; }; var identity = function identity(x) { return x; }; /** * Get property defined by dot/array notation in string, returns undefined if not found * * @link https://gist.github.com/jeneg/9767afdcca45601ea44930ea03e0febf#gistcomment-1935901 * * @param {Object} obj * @param {string|Array} path * @return {*} */ var getRaw = function getRaw(obj, path) { var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; // 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 // 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 && !isUndefinedOrNull(obj = obj[step]); }) ? obj : isNull(obj) ? null : defaultValue; }; /** * 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; var value = getRaw(obj, path); return isUndefinedOrNull(value) ? defaultValue : value; }; /** * Utilities to get information about the current environment */ 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') || getEnv('NODE_ENV') === 'production'; }; /** * 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 (IS_BROWSER) { 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 (HAS_PROMISE_SUPPORT) { 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 (HAS_MUTATION_OBSERVER_SUPPORT) { return false; } else { warn("".concat(source, ": Requires MutationObserver support.")); return true; } }; var BvConfig = /*#__PURE__*/function () { function BvConfig() { _classCallCheck(this, BvConfig); this.$_config = {}; } // Method to merge in user config parameters _createClass(BvConfig, [{ key: "setConfig", value: function setConfig() { var _this = this; var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; /* istanbul ignore next */ if (!isPlainObject(config)) { return; } var configKeys = getOwnPropertyNames(config); configKeys.forEach(function (key) { /* istanbul ignore next */ var subConfig = config[key]; if (key === 'breakpoints') { /* istanbul ignore if */ if (!isArray(subConfig) || subConfig.length < 2 || subConfig.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[key] = cloneDeep(subConfig); } } else if (isPlainObject(subConfig)) { // Component prop defaults _this.$_config[key] = getOwnPropertyNames(subConfig).reduce(function (config, prop) { if (!isUndefined(subConfig[prop])) { config[prop] = cloneDeep(subConfig[prop]); } return config; }, _this.$_config[key] || {}); } }); } // Clear the config }, { key: "resetConfig", value: function resetConfig() { this.$_config = {}; } // Returns a deep copy of the user config }, { key: "getConfig", value: function getConfig() { return cloneDeep(this.$_config); } // Returns a deep copy of the config value }, { key: "getConfigValue", value: function getConfigValue(key) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; return cloneDeep(getRaw(this.$_config, key, defaultValue)); } }]); return BvConfig; }(); // Method for applying a global config var setConfig = function setConfig() { var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var Vue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Vue__default['default']; // 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.prototype[PROP_NAME] = Vue__default['default'].prototype[PROP_NAME] = Vue.prototype[PROP_NAME] || Vue__default['default'].prototype[PROP_NAME] || new BvConfig(); // Apply the config values Vue.prototype[PROP_NAME].setConfig(config); }; // Method for resetting the user config /** * 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.org/docs#using-module-bundlers'].join('\n'); return function (Vue) { /* istanbul ignore next */ if (!checkMultipleVueWarned && Vue__default['default'] !== Vue && !IS_JSDOM) { 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(_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 (HAS_WINDOW_SUPPORT && window.Vue) { window.Vue.use(VuePlugin); } /* istanbul ignore next */ if (HAS_WINDOW_SUPPORT && VuePlugin.NAME) { window[VuePlugin.NAME] = VuePlugin; } }; // Component names var NAME_ALERT = 'BAlert'; var NAME_ASPECT = 'BAspect'; var NAME_AVATAR = 'BAvatar'; var NAME_AVATAR_GROUP = 'BAvatarGroup'; var NAME_BADGE = 'BBadge'; var NAME_BREADCRUMB = 'BBreadcrumb'; var NAME_BREADCRUMB_ITEM = 'BBreadcrumbItem'; var NAME_BREADCRUMB_LINK = 'BBreadcrumbLink'; var NAME_BUTTON = 'BButton'; var NAME_BUTTON_CLOSE = 'BButtonClose'; var NAME_BUTTON_GROUP = 'BButtonGroup'; var NAME_BUTTON_TOOLBAR = 'BButtonToolbar'; var NAME_CALENDAR = 'BCalendar'; var NAME_CARD = 'BCard'; var NAME_CARD_BODY = 'BCardBody'; var NAME_CARD_FOOTER = 'BCardFooter'; var NAME_CARD_GROUP = 'BCardGroup'; var NAME_CARD_HEADER = 'BCardHeader'; var NAME_CARD_IMG = 'BCardImg'; var NAME_CARD_IMG_LAZY = 'BCardImgLazy'; var NAME_CARD_SUB_TITLE = 'BCardSubTitle'; var NAME_CARD_TEXT = 'BCardText'; var NAME_CARD_TITLE = 'BCardTitle'; var NAME_CAROUSEL = 'BCarousel'; var NAME_CAROUSEL_SLIDE = 'BCarouselSlide'; var NAME_COL = 'BCol'; var NAME_COLLAPSE = 'BCollapse'; var NAME_CONTAINER = 'BContainer'; var NAME_DROPDOWN = 'BDropdown'; var NAME_DROPDOWN_DIVIDER = 'BDropdownDivider'; var NAME_DROPDOWN_FORM = 'BDropdownForm'; var NAME_DROPDOWN_GROUP = 'BDropdownGroup'; var NAME_DROPDOWN_HEADER = 'BDropdownHeader'; var NAME_DROPDOWN_ITEM = 'BDropdownItem'; var NAME_DROPDOWN_ITEM_BUTTON = 'BDropdownItemButton'; var NAME_DROPDOWN_TEXT = 'BDropdownText'; var NAME_EMBED = 'BEmbed'; var NAME_FORM = 'BForm'; var NAME_FORM_CHECKBOX = 'BFormCheckbox'; var NAME_FORM_CHECKBOX_GROUP = 'BFormCheckboxGroup'; var NAME_FORM_DATALIST = 'BFormDatalist'; var NAME_FORM_DATEPICKER = 'BFormDatepicker'; var NAME_FORM_FILE = 'BFormFile'; var NAME_FORM_GROUP = 'BFormGroup'; var NAME_FORM_INPUT = 'BFormInput'; var NAME_FORM_INVALID_FEEDBACK = 'BFormInvalidFeedback'; var NAME_FORM_RADIO = 'BFormRadio'; var NAME_FORM_RADIO_GROUP = 'BFormRadioGroup'; var NAME_FORM_RATING = 'BFormRating'; var NAME_FORM_ROW = 'BFormRow'; var NAME_FORM_SELECT = 'BFormSelect'; var NAME_FORM_SELECT_OPTION = 'BFormSelectOption'; var NAME_FORM_SELECT_OPTION_GROUP = 'BFormSelectOptionGroup'; var NAME_FORM_SPINBUTTON = 'BFormSpinbutton'; var NAME_FORM_TAG = 'BFormTag'; var NAME_FORM_TAGS = 'BFormTags'; var NAME_FORM_TEXT = 'BFormText'; var NAME_FORM_TEXTAREA = 'BFormTextarea'; var NAME_FORM_TIMEPICKER = 'BFormTimepicker'; var NAME_FORM_VALID_FEEDBACK = 'BFormValidFeedback'; var NAME_ICON = 'BIcon'; var NAME_ICONSTACK = 'BIconstack'; var NAME_ICON_BASE = 'BIconBase'; var NAME_IMG = 'BImg'; var NAME_IMG_LAZY = 'BImgLazy'; var NAME_INPUT_GROUP = 'BInputGroup'; var NAME_INPUT_GROUP_ADDON = 'BInputGroupAddon'; var NAME_INPUT_GROUP_APPEND = 'BInputGroupAppend'; var NAME_INPUT_GROUP_PREPEND = 'BInputGroupPrepend'; var NAME_INPUT_GROUP_TEXT = 'BInputGroupText'; var NAME_JUMBOTRON = 'BJumbotron'; var NAME_LINK = 'BLink'; var NAME_LIST_GROUP = 'BListGroup'; var NAME_LIST_GROUP_ITEM = 'BListGroupItem'; var NAME_MEDIA = 'BMedia'; var NAME_MEDIA_ASIDE = 'BMediaAside'; var NAME_MEDIA_BODY = 'BMediaBody'; var NAME_MODAL = 'BModal'; var NAME_MSG_BOX = 'BMsgBox'; var NAME_NAV = 'BNav'; var NAME_NAVBAR = 'BNavbar'; var NAME_NAVBAR_BRAND = 'BNavbarBrand'; var NAME_NAVBAR_NAV = 'BNavbarNav'; var NAME_NAVBAR_TOGGLE = 'BNavbarToggle'; var NAME_NAV_FORM = 'BNavForm'; var NAME_NAV_ITEM = 'BNavItem'; var NAME_NAV_ITEM_DROPDOWN = 'BNavItemDropdown'; var NAME_NAV_TEXT = 'BNavText'; var NAME_OVERLAY = 'BOverlay'; var NAME_PAGINATION = 'BPagination'; var NAME_PAGINATION_NAV = 'BPaginationNav'; var NAME_POPOVER = 'BPopover'; var NAME_PROGRESS = 'BProgress'; var NAME_PROGRESS_BAR = 'BProgressBar'; var NAME_ROW = 'BRow'; var NAME_SIDEBAR = 'BSidebar'; var NAME_SKELETON = 'BSkeleton'; var NAME_SKELETON_ICON = 'BSkeletonIcon'; var NAME_SKELETON_IMG = 'BSkeletonImg'; var NAME_SKELETON_TABLE = 'BSkeletonTable'; var NAME_SKELETON_WRAPPER = 'BSkeletonWrapper'; var NAME_SPINNER = 'BSpinner'; var NAME_TAB = 'BTab'; var NAME_TABLE = 'BTable'; var NAME_TABLE_CELL = 'BTableCell'; var NAME_TABLE_LITE = 'BTableLite'; var NAME_TABLE_SIMPLE = 'BTableSimple'; var NAME_TABS = 'BTabs'; var NAME_TBODY = 'BTbody'; var NAME_TFOOT = 'BTfoot'; var NAME_TH = 'BTh'; var NAME_THEAD = 'BThead'; var NAME_TIME = 'BTime'; var NAME_TOAST = 'BToast'; var NAME_TOASTER = 'BToaster'; var NAME_TOOLTIP = 'BTooltip'; var NAME_TR = 'BTr'; // Helper component names var NAME_COLLAPSE_HELPER = 'BVCollapse'; var NAME_FORM_BUTTON_LABEL_CONTROL = 'BVFormBtnLabelControl'; var NAME_FORM_RATING_STAR = 'BVFormRatingStar'; var NAME_POPOVER_HELPER = 'BVPopover'; var NAME_POPOVER_TEMPLATE = 'BVPopoverTemplate'; var NAME_POPPER = 'BVPopper'; var NAME_TAB_BUTTON_HELPER = 'BVTabButton'; var NAME_TOAST_POP = 'BVToastPop'; var NAME_TOOLTIP_HELPER = 'BVTooltip'; var NAME_TOOLTIP_TEMPLATE = 'BVTooltipTemplate'; var NAME_TRANSITION = 'BVTransition'; var NAME_TRANSPORTER = 'BVTransporter'; var NAME_TRANSPORTER_TARGET = 'BVTransporterTarget'; var EVENT_NAME_ACTIVATE_TAB = 'activate-tab'; var EVENT_NAME_BLUR = 'blur'; var EVENT_NAME_CANCEL = 'cancel'; var EVENT_NAME_CHANGE = 'change'; var EVENT_NAME_CHANGED = 'changed'; var EVENT_NAME_CLICK = 'click'; var EVENT_NAME_CLOSE = 'close'; var EVENT_NAME_CONTEXT = 'context'; var EVENT_NAME_CONTEXT_CHANGED = 'context-changed'; var EVENT_NAME_DESTROYED = 'destroyed'; var EVENT_NAME_DISABLE = 'disable'; var EVENT_NAME_DISABLED = 'disabled'; var EVENT_NAME_DISMISSED = 'dismissed'; var EVENT_NAME_DISMISS_COUNT_DOWN = 'dismiss-count-down'; var EVENT_NAME_ENABLE = 'enable'; var EVENT_NAME_ENABLED = 'enabled'; var EVENT_NAME_FILTERED = 'filtered'; var EVENT_NAME_FIRST = 'first'; var EVENT_NAME_FOCUSIN = 'focusin'; var EVENT_NAME_FOCUSOUT = 'focusout'; var EVENT_NAME_HEAD_CLICKED = 'head-clicked'; var EVENT_NAME_HIDDEN = 'hidden'; var EVENT_NAME_HIDE = 'hide'; var EVENT_NAME_IMG_ERROR = 'img-error'; var EVENT_NAME_INPUT = 'input'; var EVENT_NAME_LAST = 'last'; var EVENT_NAME_MOUSEENTER = 'mouseenter'; var EVENT_NAME_MOUSELEAVE = 'mouseleave'; var EVENT_NAME_NEXT = 'next'; var EVENT_NAME_OK = 'ok'; var EVENT_NAME_OPEN = 'open'; var EVENT_NAME_PAGE_CLICK = 'page-click'; var EVENT_NAME_PAUSED = 'paused'; var EVENT_NAME_PREV = 'prev'; var EVENT_NAME_REFRESH = 'refresh'; var EVENT_NAME_REFRESHED = 'refreshed'; var EVENT_NAME_REMOVE = 'remove'; var EVENT_NAME_ROW_CLICKED = 'row-clicked'; var EVENT_NAME_ROW_CONTEXTMENU = 'row-contextmenu'; var EVENT_NAME_ROW_DBLCLICKED = 'row-dblclicked'; var EVENT_NAME_ROW_HOVERED = 'row-hovered'; var EVENT_NAME_ROW_MIDDLE_CLICKED = 'row-middle-clicked'; var EVENT_NAME_ROW_SELECTED = 'row-selected'; var EVENT_NAME_ROW_UNHOVERED = 'row-unhovered'; var EVENT_NAME_SELECTED = 'selected'; var EVENT_NAME_SHOW = 'show'; var EVENT_NAME_SHOWN = 'shown'; var EVENT_NAME_SLIDING_END = 'sliding-end'; var EVENT_NAME_SLIDING_START = 'sliding-start'; var EVENT_NAME_SORT_CHANGED = 'sort-changed'; var EVENT_NAME_TAG_STATE = 'tag-state'; var EVENT_NAME_TOGGLE = 'toggle'; var EVENT_NAME_UNPAUSED = 'unpaused'; var EVENT_NAME_UPDATE = 'update'; var HOOK_EVENT_NAME_BEFORE_DESTROY = 'hook:beforeDestroy'; var HOOK_EVENT_NAME_DESTROYED = 'hook:destroyed'; var MODEL_EVENT_NAME_PREFIX = 'update:'; var ROOT_EVENT_NAME_PREFIX = 'bv'; var ROOT_EVENT_NAME_SEPARATOR = '::'; var EVENT_OPTIONS_PASSIVE = { passive: true }; var EVENT_OPTIONS_NO_CAPTURE = { passive: true, capture: false }; // General types var PROP_TYPE_ANY = undefined; var PROP_TYPE_ARRAY = Array; var PROP_TYPE_BOOLEAN = Boolean; var PROP_TYPE_DATE = Date; var PROP_TYPE_FUNCTION = Function; var PROP_TYPE_NUMBER = Number; var PROP_TYPE_OBJECT = Object; var PROP_TYPE_REG_EXP = RegExp; var PROP_TYPE_STRING = String; // Multiple types var PROP_TYPE_ARRAY_FUNCTION = [PROP_TYPE_ARRAY, PROP_TYPE_FUNCTION]; var PROP_TYPE_ARRAY_OBJECT = [PROP_TYPE_ARRAY, PROP_TYPE_OBJECT]; var PROP_TYPE_ARRAY_OBJECT_STRING = [PROP_TYPE_ARRAY, PROP_TYPE_OBJECT, PROP_TYPE_STRING]; var PROP_TYPE_ARRAY_STRING = [PROP_TYPE_ARRAY, PROP_TYPE_STRING]; var PROP_TYPE_BOOLEAN_NUMBER = [PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER]; var PROP_TYPE_BOOLEAN_NUMBER_STRING = [PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER, PROP_TYPE_STRING]; var PROP_TYPE_BOOLEAN_STRING = [PROP_TYPE_BOOLEAN, PROP_TYPE_STRING]; var PROP_TYPE_DATE_STRING = [PROP_TYPE_DATE, PROP_TYPE_STRING]; var PROP_TYPE_FUNCTION_STRING = [PROP_TYPE_FUNCTION, PROP_TYPE_STRING]; var PROP_TYPE_NUMBER_STRING = [PROP_TYPE_NUMBER, PROP_TYPE_STRING]; var PROP_TYPE_NUMBER_OBJECT_STRING = [PROP_TYPE_NUMBER, PROP_TYPE_OBJECT, PROP_TYPE_STRING]; var PROP_TYPE_OBJECT_FUNCTION = [PROP_TYPE_OBJECT, PROP_TYPE_FUNCTION]; var PROP_TYPE_OBJECT_STRING = [PROP_TYPE_OBJECT, PROP_TYPE_STRING]; var SLOT_NAME_ADD_BUTTON_TEXT = 'add-button-text'; var SLOT_NAME_APPEND = 'append'; var SLOT_NAME_ASIDE = 'aside'; var SLOT_NAME_BADGE = 'badge'; var SLOT_NAME_BOTTOM_ROW = 'bottom-row'; var SLOT_NAME_BUTTON_CONTENT = 'button-content'; var SLOT_NAME_CUSTOM_FOOT = 'custom-foot'; var SLOT_NAME_DECREMENT = 'decrement'; var SLOT_NAME_DEFAULT = 'default'; var SLOT_NAME_DESCRIPTION = 'description'; var SLOT_NAME_DISMISS = 'dismiss'; var SLOT_NAME_DROP_PLACEHOLDER = 'drop-placeholder'; var SLOT_NAME_ELLIPSIS_TEXT = 'ellipsis-text'; var SLOT_NAME_EMPTY = 'empty'; var SLOT_NAME_EMPTYFILTERED = 'emptyfiltered'; var SLOT_NAME_FILE_NAME = 'file-name'; var SLOT_NAME_FIRST = 'first'; var SLOT_NAME_FIRST_TEXT = 'first-text'; var SLOT_NAME_FOOTER = 'footer'; var SLOT_NAME_HEADER = 'header'; var SLOT_NAME_HEADER_CLOSE = 'header-close'; var SLOT_NAME_ICON_CLEAR = 'icon-clear'; var SLOT_NAME_ICON_EMPTY = 'icon-empty'; var SLOT_NAME_ICON_FULL = 'icon-full'; var SLOT_NAME_ICON_HALF = 'icon-half'; var SLOT_NAME_IMG = 'img'; var SLOT_NAME_INCREMENT = 'increment'; var SLOT_NAME_INVALID_FEEDBACK = 'invalid-feedback'; var SLOT_NAME_LABEL = 'label'; var SLOT_NAME_LAST_TEXT = 'last-text'; var SLOT_NAME_LEAD = 'lead'; var SLOT_NAME_LOADING = 'loading'; var SLOT_NAME_MODAL_BACKDROP = 'modal-backdrop'; var SLOT_NAME_MODAL_CANCEL = 'modal-cancel'; var SLOT_NAME_MODAL_FOOTER = 'modal-footer'; var SLOT_NAME_MODAL_HEADER = 'modal-header'; var SLOT_NAME_MODAL_HEADER_CLOSE = 'modal-header-close'; var SLOT_NAME_MODAL_OK = 'modal-ok'; var SLOT_NAME_MODAL_TITLE = 'modal-title'; var SLOT_NAME_NAV_NEXT_DECADE = 'nav-next-decade'; var SLOT_NAME_NAV_NEXT_MONTH = 'nav-next-month'; var SLOT_NAME_NAV_NEXT_YEAR = 'nav-next-year'; var SLOT_NAME_NAV_PEV_DECADE = 'nav-prev-decade'; var SLOT_NAME_NAV_PEV_MONTH = 'nav-prev-month'; var SLOT_NAME_NAV_PEV_YEAR = 'nav-prev-year'; var SLOT_NAME_NAV_THIS_MONTH = 'nav-this-month'; var SLOT_NAME_NEXT_TEXT = 'next-text'; var SLOT_NAME_OVERLAY = 'overlay'; var SLOT_NAME_PAGE = 'page'; var SLOT_NAME_PLACEHOLDER = 'placeholder'; var SLOT_NAME_PREPEND = 'prepend'; var SLOT_NAME_PREV_TEXT = 'prev-text'; var SLOT_NAME_ROW_DETAILS = 'row-details'; var SLOT_NAME_TABLE_BUSY = 'table-busy'; var SLOT_NAME_TABLE_CAPTION = 'table-caption'; var SLOT_NAME_TABLE_COLGROUP = 'table-colgroup'; var SLOT_NAME_TABS_END = 'tabs-end'; var SLOT_NAME_TABS_START = 'tabs-start'; var SLOT_NAME_TEXT = 'text'; var SLOT_NAME_THEAD_TOP = 'thead-top'; var SLOT_NAME_TITLE = 'title'; var SLOT_NAME_TOAST_TITLE = 'toast-title'; var SLOT_NAME_TOP_ROW = 'top-row'; var SLOT_NAME_VALID_FEEDBACK = 'valid-feedback'; var from = function from() { return Array.from.apply(Array, arguments); }; // --- 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); }; // --- Utilities --- var createArray = function createArray(length, fillFn) { var mapFn = isFunction(fillFn) ? fillFn : function () { return fillFn; }; return Array.apply(null, { length: length }).map(mapFn); }; var flatten = function flatten(array) { return array.reduce(function (result, item) { return concat(result, item); }, []); }; var flattenDeep = function flattenDeep(array) { return array.reduce(function (result, item) { return concat(result, Array.isArray(item) ? flattenDeep(item) : item); }, []); }; // Number utilities // Converts a value (string, number, etc.) to an integer number // Assumes radix base 10 var toInteger = function toInteger(value) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : NaN; var integer = parseInt(value, 10); return isNaN(integer) ? defaultValue : integer; }; // Converts a value (string, number, etc.) to a number var toFloat = function toFloat(value) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : NaN; var float = parseFloat(value); return isNaN(float) ? defaultValue : float; }; // 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)); }; // String 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); }; // Converts a string, including strings in camelCase or snake_case, into Start Case // It keeps original single quote and hyphen in the word // https://github.com/UrbanCompass/to-start-case 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(); }); }; // 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 ELEMENT_PROTO = Element.prototype; var TABABLE_SELECTOR = ['button', '[href]:not(.disabled)', 'input', 'select', 'textarea', '[tabindex]', '[contenteditable]'].map(function (s) { return "".concat(s, ":not(:disabled):not([disabled])"); }).join(', '); // --- Normalization utils --- // See: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill /* istanbul ignore next */ var matchesEl = ELEMENT_PROTO.matches || ELEMENT_PROTO.msMatchesSelector || ELEMENT_PROTO.webkitMatchesSelector; // See: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest /* istanbul ignore next */ var closestEl = ELEMENT_PROTO.closest || function (sel) { 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 /* istanbul ignore next: JSDOM always returns the first option */ var requestAF = WINDOW.requestAnimationFrame || WINDOW.webkitRequestAnimationFrame || WINDOW.mozRequestAnimationFrame || WINDOW.msRequestAnimationFrame || WINDOW.oRequestAnimationFrame || // Fallback, but not a true polyfill // Only needed for Opera Mini /* istanbul ignore next */ function (cb) { return setTimeout(cb, 16); }; var MutationObs = WINDOW.MutationObserver || WINDOW.WebKitMutationObserver || WINDOW.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); }; // Get the currently active HTML element var getActiveElement = function getActiveElement() { var excludes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var activeElement = DOCUMENT.activeElement; return activeElement && !excludes.some(function (el) { return el === activeElement; }) ? activeElement : null; }; // Returns `true` if a tag's name equals `name` var isTag = function isTag(tag, name) { return toString$1(tag).toLowerCase() === toString$1(name).toLowerCase(); }; // Determine if an HTML element is the currently active element var isActiveElement = function isActiveElement(el) { return isElement(el) && el === getActiveElement(); }; // Determine if an HTML element is visible - Faster than CSS check var isVisible = function isVisible(el) { if (!isElement(el) || !el.parentNode || !contains(DOCUMENT.body, el)) { // Note this can fail for shadow dom elements since they // are not a direct descendant of document.body return false; } if (getStyle(el, '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 : DOCUMENT).querySelectorAll(selector)); }; // Select a single element, returns `null` if not found var select = function select(selector, root) { return (isElement(root) ? root : DOCUMENT).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 DOCUMENT.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, value) { if (attr && isElement(el)) { el.setAttribute(attr, value); } }; // Remove an attribute from an element var removeAttr = function removeAttr(el, attr) { if (attr && isElement(el)) { el.removeAttribute(attr); } }; // Get an attribute value from an element // Returns `null` if not found var getAttr = function getAttr(el, attr) { 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; }; // Set an style property on an element var setStyle = function setStyle(el, prop, value) { if (prop && isElement(el)) { el.style[prop] = value; } }; // Remove an style property from an element var removeStyle = function removeStyle(el, prop) { if (prop && isElement(el)) { el.style[prop] = ''; } }; // Get an style property value from an element // Returns `null` if not found var getStyle = function getStyle(el, prop) { return prop && isElement(el) ? el.style[prop] || null : 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) { var getComputedStyle = WINDOW.getComputedStyle; return getComputedStyle && isElement(el) ? 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() { var getSelection = WINDOW.getSelection; return getSelection ? WINDOW.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 += toFloat(offsetParentStyles.borderTopWidth, 0); parentOffset.left += toFloat(offsetParentStyles.borderLeftWidth, 0); } } return { top: _offset.top - parentOffset.top - toFloat(elStyles.marginTop, 0), left: _offset.left - parentOffset.left - toFloat(elStyles.marginLeft, 0) }; }; // Find all tabable elements in the given element // Assumes users have not used `tabindex` > `0` on elements var getTabables = function getTabables() { var rootEl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; return selectAll(TABABLE_SELECTOR, rootEl).filter(isVisible).filter(function (el) { return el.tabIndex > -1 && !el.disabled; }); }; // Attempt to focus an element, and return `true` if successful var attemptFocus = function attemptFocus(el) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; try { el.focus(options); } catch (_unused) {} return isActiveElement(el); }; // Attempt to blur an element, and return `true` if successful var attemptBlur = function attemptBlur(el) { try { el.blur(); } catch (_unused2) {} return !isActiveElement(el); }; 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 VueProto = Vue__default['default'].prototype; // --- Getter methods --- var getConfigValue = function getConfigValue(key) { var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var bvConfig = VueProto[PROP_NAME]; return bvConfig ? bvConfig.getConfigValue(key, defaultValue) : cloneDeep(defaultValue); }; // Method to grab a config value for a particular component var getComponentConfig = function getComponentConfig(key) { var propKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; // Return the particular config value for key if specified, // otherwise we return the full config (or an empty object if not found) return propKey ? getConfigValue("".concat(key, ".").concat(propKey), defaultValue) : getConfigValue(key, {}); }; // Get all breakpoint names var getBreakpoints = function getBreakpoints() { return getConfigValue('breakpoints', DEFAULT_BREAKPOINT); }; // Private method for caching breakpoint names var _getBreakpointsCached = memoize(function () { return getBreakpoints(); }); // Get all breakpoint names (cached) var getBreakpointsCached = function getBreakpointsCached() { return cloneDeep(_getBreakpointsCached()); }; // Get breakpoints with the smallest breakpoint set as '' // Useful for components that create breakpoint specific props var getBreakpointsUpCached = memoize(function () { var breakpoints = getBreakpointsCached(); breakpoints[0] = ''; return breakpoints; }); // Get breakpoints with the largest breakpoint set as '' var prefixPropName = function prefixPropName(prefix, value) { return prefix + upperFirst(value); }; // Remove a prefix from a property var unprefixPropName = function unprefixPropName(prefix, value) { return lowerFirst(value.replace(prefix, '')); }; // 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 var suffixPropName = function suffixPropName(suffix, value) { return value + (suffix ? upperFirst(suffix) : ''); }; // Generates a prop object var makeProp = function makeProp() { var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : PROP_TYPE_ANY; var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var requiredOrValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var validator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined; var required = requiredOrValidator === true; validator = required ? validator : requiredOrValidator; return _objectSpread2(_objectSpread2(_objectSpread2({}, type ? { type: type } : {}), required ? { required: required } : isUndefined(value) ? {} : { default: isObject(value) ? function () { return value; } : value }), isUndefined(validator) ? {} : { validator: validator }); }; // 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 var copyProps = function copyProps(props) { var transformFn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : identity; if (isArray(props)) { return props.map(transformFn); } var copied = {}; for (var prop in props) { /* istanbul ignore else */ if (hasOwnProperty(props, 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; }; // 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 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; }, {}); }; // Make a prop object configurable by global configuration // Replaces the current `default` key of each prop with a `getComponentConfig()` // call that falls back to the current default value of the prop var makePropConfigurable = function makePropConfigurable(prop, key, componentKey) { return _objectSpread2(_objectSpread2({}, cloneDeep(prop)), {}, { default: function bvConfigurablePropDefault() { var value = getComponentConfig(componentKey, key, prop.default); return isFunction(value) ? value() : value; } }); }; // Make a props object configurable by global configuration // Replaces the current `default` key of each prop with a `getComponentConfig()` // call that falls back to the current default value of the prop var makePropsConfigurable = function makePropsConfigurable(props, componentKey) { return keys(props).reduce(function (result, key) { return _objectSpread2(_objectSpread2({}, result), {}, _defineProperty({}, key, makePropConfigurable(props[key], key, componentKey))); }, {}); }; // Get function name we use in `makePropConfigurable()` // for the prop default value override to compare // against in `hasPropFunction()` var configurablePropDefaultFnName = makePropConfigurable({}, '', '').default.name; // Detect wether the given value is currently a function // and isn't the props default function var hasPropFunction = function hasPropFunction(fn) { return isFunction(fn) && fn.name !== configurablePropDefaultFnName; }; var makeModelMixin = function makeModelMixin(prop) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$type = _ref.type, type = _ref$type === void 0 ? PROP_TYPE_ANY : _ref$type, _ref$defaultValue = _ref.defaultValue, defaultValue = _ref$defaultValue === void 0 ? undefined : _ref$defaultValue, _ref$validator = _ref.validator, validator = _ref$validator === void 0 ? undefined : _ref$validator, _ref$event = _ref.event, event = _ref$event === void 0 ? EVENT_NAME_INPUT : _ref$event; var props = _defineProperty({}, prop, makeProp(type, defaultValue, validator)); // @vue/component var mixin = Vue__default['default'].extend({ model: { prop: prop, event: event }, props: props }); return { mixin: mixin, props: props, prop: prop, event: event }; }; // 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; }; var normalizeSlotMixin = Vue__default['default'].extend({ methods: { // Returns `true` if the either a `$scopedSlot` or `$slot` exists with the specified name // `name` can be a string name or an array of names hasNormalizedSlot: function hasNormalizedSlot$1() { var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : SLOT_NAME_DEFAULT; var scopedSlots = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.$scopedSlots; var slots = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.$slots; return hasNormalizedSlot(name, scopedSlots, slots); }, // Returns an array of rendered VNodes if slot found, otherwise `undefined` // `name` can be a string name or an array of names normalizeSlot: function normalizeSlot$1() { var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : SLOT_NAME_DEFAULT; var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var scopedSlots = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.$scopedSlots; var slots = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : this.$slots; var vNodes = normalizeSlot(name, scope, scopedSlots, slots); return vNodes ? concat(vNodes) : vNodes; } } }); // 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 (HAS_PASSIVE_EVENT_SUPPORT) { 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, eventName, handler, options) { if (el && el.addEventListener) { el.addEventListener(eventName, handler, parseEventOptions(options)); } }; // Remove an event listener from an element var eventOff = function eventOff(el, eventName, handler, options) { if (el && el.removeEventListener) { el.removeEventListener(eventName, 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); }; // Utility method to prevent the default event handling and propagation var stopEvent = function stopEvent(event) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$preventDefault = _ref.preventDefault, preventDefault = _ref$preventDefault === void 0 ? true : _ref$preventDefault, _ref$propagation = _ref.propagation, propagation = _ref$propagation === void 0 ? true : _ref$propagation, _ref$immediatePropaga = _ref.immediatePropagation, immediatePropagation = _ref$immediatePropaga === void 0 ? false : _ref$immediatePropaga; if (preventDefault) { event.preventDefault(); } if (propagation) { event.stopPropagation(); } if (immediatePropagation) { event.stopImmediatePropagation(); } }; // Helper method to convert a component/directive name to a base event name // `getBaseEventName('BNavigationItem')` => 'navigation-item' // `getBaseEventName('BVToggle')` => 'toggle' var getBaseEventName = function getBaseEventName(value) { return kebabCase(value.replace(RX_BV_PREFIX, '')); }; // Get a root event name by component/directive and event name // `getBaseEventName('BModal', 'show')` => 'bv::modal::show' var getRootEventName = function getRootEventName(name, eventName) { return [ROOT_EVENT_NAME_PREFIX, getBaseEventName(name), eventName].join(ROOT_EVENT_NAME_SEPARATOR); }; // Get a root action event name by component/directive and action name // `getRootActionEventName('BModal', 'show')` => 'bv::show::modal' var getRootActionEventName = function getRootActionEventName(name, actionName) { return [ROOT_EVENT_NAME_PREFIX, actionName, getBaseEventName(name)].join(ROOT_EVENT_NAME_SEPARATOR); }; var props = makePropsConfigurable({ ariaLabel: makeProp(PROP_TYPE_STRING, 'Close'), content: makeProp(PROP_TYPE_STRING, '×'), disabled: makeProp(PROP_TYPE_BOOLEAN, false), textVariant: makeProp(PROP_TYPE_STRING) }, NAME_BUTTON_CLOSE); // --- Main component --- // @vue/component var BButtonClose = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BUTTON_CLOSE, 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(event) { // 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(event)) { stopEvent(event); } } } }; // Careful not to override the default slot with innerHTML if (!hasNormalizedSlot(SLOT_NAME_DEFAULT, $scopedSlots, $slots)) { componentData.domProps = { innerHTML: props.content }; } return h('button', a(data, componentData), normalizeSlot(SLOT_NAME_DEFAULT, {}, $scopedSlots, $slots)); } }); var NO_FADE_PROPS = { name: '', enterClass: '', enterActiveClass: '', enterToClass: 'show', leaveClass: 'show', leaveActiveClass: '', leaveToClass: '' }; var FADE_PROPS = _objectSpread2(_objectSpread2({}, NO_FADE_PROPS), {}, { enterActiveClass: 'fade', leaveActiveClass: 'fade' }); // --- Props --- var props$1 = { // Has no effect if `trans-props` provided appear: makeProp(PROP_TYPE_BOOLEAN, false), // Can be overridden by user supplied `trans-props` mode: makeProp(PROP_TYPE_STRING), // Only applicable to the built in transition // Has no effect if `trans-props` provided noFade: makeProp(PROP_TYPE_BOOLEAN, false), // For user supplied transitions (if needed) transProps: makeProp(PROP_TYPE_OBJECT) }; // --- Main component --- // @vue/component var BVTransition = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TRANSITION, functional: true, props: props$1, 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(_objectSpread2({}, transProps), {}, { appear: true, appearClass: transProps.enterClass, appearActiveClass: transProps.enterActiveClass, appearToClass: transProps.enterToClass }); } } transProps = _objectSpread2(_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); } }); var _watch; var _makeModelMixin = makeModelMixin('show', { type: PROP_TYPE_BOOLEAN_NUMBER_STRING, defaultValue: false }), modelMixin = _makeModelMixin.mixin, modelProps = _makeModelMixin.props, MODEL_PROP_NAME = _makeModelMixin.prop, MODEL_EVENT_NAME = _makeModelMixin.event; // --- Helper methods --- // Convert `show` value to a number var parseCountDown = function parseCountDown(show) { if (show === '' || isBoolean(show)) { return 0; } show = toInteger(show, 0); 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, 0) < 1) { // Boolean will always return false for the above comparison return false; } return !!show; }; // --- Props --- var props$2 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, modelProps), {}, { dismissLabel: makeProp(PROP_TYPE_STRING, 'Close'), dismissible: makeProp(PROP_TYPE_BOOLEAN, false), fade: makeProp(PROP_TYPE_BOOLEAN, false), variant: makeProp(PROP_TYPE_STRING, 'info') })), NAME_ALERT); // --- Main component --- // @vue/component var BAlert = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_ALERT, mixins: [modelMixin, normalizeSlotMixin], props: props$2, data: function data() { return { countDown: 0, // If initially shown, we need to set these for SSR localShow: parseShow(this[MODEL_PROP_NAME]) }; }, watch: (_watch = {}, _defineProperty(_watch, MODEL_PROP_NAME, function (newValue) { this.countDown = parseCountDown(newValue); this.localShow = parseShow(newValue); }), _defineProperty(_watch, "countDown", function countDown(newValue) { var _this = this; this.clearCountDownInterval(); var show = this[MODEL_PROP_NAME]; // Ignore if `show` transitions to a boolean value if (isNumeric(show)) { this.$emit(EVENT_NAME_DISMISS_COUNT_DOWN, newValue); // Update the v-model if needed if (show !== newValue) { this.$emit(MODEL_EVENT_NAME, newValue); } if (newValue > 0) { this.localShow = true; this.$_countDownTimeout = setTimeout(function () { _this.countDown--; }, 1000); } else { // Slightly delay the hide to allow any UI updates this.$nextTick(function () { requestAF(function () { _this.localShow = false; }); }); } } }), _defineProperty(_watch, "localShow", function localShow(newValue) { var show = this[MODEL_PROP_NAME]; // Only emit dismissed events for dismissible or auto-dismissing alerts if (!newValue && (this.dismissible || isNumeric(show))) { this.$emit(EVENT_NAME_DISMISSED); } // Only emit booleans if we weren't passed a number via v-model if (!isNumeric(show) && show !== newValue) { this.$emit(MODEL_EVENT_NAME, newValue); } }), _watch), created: function created() { // Create private non-reactive props this.$_filterTimer = null; var show = this[MODEL_PROP_NAME]; this.countDown = parseCountDown(show); this.localShow = parseShow(show); }, beforeDestroy: function beforeDestroy() { this.clearCountDownInterval(); }, methods: { dismiss: function dismiss() { this.clearCountDownInterval(); this.countDown = 0; this.localShow = false; }, clearCountDownInterval: function clearCountDownInterval() { clearTimeout(this.$_countDownTimeout); this.$_countDownTimeout = null; } }, render: function render(h) { var $alert = h(); if (this.localShow) { var dismissible = this.dismissible, variant = this.variant; var $dismissButton = h(); if (dismissible) { // Add dismiss button $dismissButton = h(BButtonClose, { attrs: { 'aria-label': this.dismissLabel }, on: { click: this.dismiss } }, [this.normalizeSlot(SLOT_NAME_DISMISS)]); } $alert = h('div', { staticClass: 'alert', class: _defineProperty({ 'alert-dismissible': dismissible }, "alert-".concat(variant), variant), attrs: { role: 'alert', 'aria-live': 'polite', 'aria-atomic': true }, key: this[COMPONENT_UID_KEY] }, [$dismissButton, this.normalizeSlot()]); } return h(BVTransition, { props: { noFade: !this.fade } }, [$alert]); } }); var AlertPlugin = /*#__PURE__*/pluginFactory({ components: { BAlert: BAlert } }); // Math utilty functions var mathMin = Math.min; var mathMax = Math.max; var mathAbs = Math.abs; var mathCeil = Math.ceil; var mathFloor = Math.floor; var mathPow = Math.pow; var mathRound = Math.round; var CLASS_NAME = 'b-aspect'; // --- Props --- var props$3 = makePropsConfigurable({ // Accepts a number (i.e. `16 / 9`, `1`, `4 / 3`) // Or a string (i.e. '16/9', '16:9', '4:3' '1:1') aspect: makeProp(PROP_TYPE_NUMBER_STRING, '1:1'), tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_ASPECT); // --- Main component --- // @vue/component var BAspect = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_ASPECT, mixins: [normalizeSlotMixin], props: props$3, computed: { padding: function padding() { var aspect = this.aspect; var ratio = 1; if (RX_ASPECT.test(aspect)) { // Width and/or Height can be a decimal value below `1`, so // we only fallback to `1` if the value is `0` or `NaN` var _aspect$split$map = aspect.split(RX_ASPECT_SEPARATOR).map(function (v) { return toFloat(v) || 1; }), _aspect$split$map2 = _slicedToArray(_aspect$split$map, 2), width = _aspect$split$map2[0], height = _aspect$split$map2[1]; ratio = width / height; } else { ratio = toFloat(aspect) || 1; } return "".concat(100 / mathAbs(ratio), "%"); } }, render: function render(h) { var $sizer = h('div', { staticClass: "".concat(CLASS_NAME, "-sizer flex-grow-1"), style: { paddingBottom: this.padding, height: 0 } }); var $content = h('div', { staticClass: "".concat(CLASS_NAME, "-content flex-grow-1 w-100 mw-100"), style: { marginLeft: '-100%' } }, this.normalizeSlot()); return h(this.tag, { staticClass: "".concat(CLASS_NAME, " d-flex") }, [$sizer, $content]); } }); var AspectPlugin = /*#__PURE__*/pluginFactory({ components: { BAspect: BAspect } }); var ANCHOR_TAG = 'a'; // 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(RX_ENCODE_REVERSE, encodeReserveReplacer).replace(RX_ENCODED_COMMA, ','); }; 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 value = obj[key]; if (isUndefined(value)) { return ''; } else if (isNull(value)) { return encode(key); } else if (isArray(value)) { return value.reduce(function (results, value2) { if (isNull(value2)) { results.push(encode(key)); } else if (!isUndefined(value2)) { // Faster than string interpolation results.push(encode(key) + '=' + encode(value2)); } return results; }, []).join('&'); } // Faster than string interpolation return encode(key) + '=' + encode(value); }) /* 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(RX_QUERY_START, ''); if (!query) { return parsed; } query.split('&').forEach(function (param) { var parts = param.replace(RX_PLUS, ' ').split('='); var key = decode(parts.shift()); var value = parts.length > 0 ? decode(parts.join('=')) : null; if (isUndefined(parsed[key])) { parsed[key] = value; } else if (isArray(parsed[key])) { parsed[key].push(value); } else { parsed[key] = [parsed[key], value]; } }); return parsed; }; var isLink = function isLink(props) { return !!(props.href || props.to); }; var isRouterLink = function isRouterLink(tag) { return !!(tag && !isTag(tag, 'a')); }; var computeTag = function computeTag(_ref, thisOrParent) { var to = _ref.to, disabled = _ref.disabled, routerComponentName = _ref.routerComponentName; var hasRouter = !!thisOrParent.$router; if (!hasRouter || hasRouter && (disabled || !to)) { return ANCHOR_TAG; } // TODO: // Check registered components for existence of user supplied router link component name // We would need to check PascalCase, kebab-case, and camelCase versions of name: // const name = routerComponentName // const names = [name, PascalCase(name), KebabCase(name), CamelCase(name)] // exists = names.some(name => !!thisOrParent.$options.components[name]) // And may want to cache the result for performance or we just let the render fail // if the component is not registered return routerComponentName || (thisOrParent.$nuxt ? 'nuxt-link' : 'router-link'); }; var computeRel = function computeRel() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, target = _ref2.target, rel = _ref2.rel; return target === '_blank' && isNull(rel) ? 'noopener' : 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] : '/'; // Return `href` when explicitly provided if (href) { return href; } // We've checked for `$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; } // 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; }; // Base attributes needed on all icons var BASE_ATTRS = { viewBox: '0 0 16 16', width: '1em', height: '1em', focusable: 'false', role: 'img', 'aria-label': 'icon' }; // Attributes that are nulled out when stacked var STACKED_ATTRS = { width: null, height: null, focusable: null, role: null, 'aria-label': null }; // --- Props --- var props$4 = { animation: makeProp(PROP_TYPE_STRING), content: makeProp(PROP_TYPE_STRING), flipH: makeProp(PROP_TYPE_BOOLEAN, false), flipV: makeProp(PROP_TYPE_BOOLEAN, false), fontScale: makeProp(PROP_TYPE_NUMBER_STRING, 1), rotate: makeProp(PROP_TYPE_NUMBER_STRING, 0), scale: makeProp(PROP_TYPE_NUMBER_STRING, 1), shiftH: makeProp(PROP_TYPE_NUMBER_STRING, 0), shiftV: makeProp(PROP_TYPE_NUMBER_STRING, 0), stacked: makeProp(PROP_TYPE_BOOLEAN, false), title: makeProp(PROP_TYPE_STRING), variant: makeProp(PROP_TYPE_STRING) }; // --- Main component --- // Shared private base component to reduce bundle/runtime size // @vue/component var BVIconBase = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_ICON_BASE, functional: true, props: props$4, render: function render(h, _ref) { var _class; var data = _ref.data, props = _ref.props, children = _ref.children; var animation = props.animation, content = props.content, flipH = props.flipH, flipV = props.flipV, stacked = props.stacked, title = props.title, variant = props.variant; var fontScale = mathMax(toFloat(props.fontScale, 1), 0) || 1; var scale = mathMax(toFloat(props.scale, 1), 0) || 1; var rotate = toFloat(props.rotate, 0); var shiftH = toFloat(props.shiftH, 0); var shiftV = toFloat(props.shiftV, 0); // 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 16 16` (`8 8` is the center) var hasScale = flipH || flipV || scale !== 1; var hasTransforms = hasScale || rotate; var hasShift = shiftH || shiftV; var hasContent = !isUndefinedOrNull(content); var transforms = [hasTransforms ? 'translate(8 8)' : null, hasScale ? "scale(".concat((flipH ? -1 : 1) * scale, " ").concat((flipV ? -1 : 1) * scale, ")") : null, rotate ? "rotate(".concat(rotate, ")") : null, hasTransforms ? 'translate(-8 -8)' : null].filter(identity); // 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: 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(16 * shiftH / 16, " ").concat(-16 * shiftV / 16, ")") } }, [$inner]); } // Wrap in an additional `<g>` for proper animation handling if stacked if (stacked) { $inner = h('g', [$inner]); } var $title = title ? h('title', title) : null; var $content = [$title, $inner].filter(identity); return h('svg', a({ staticClass: 'b-icon bi', class: (_class = {}, _defineProperty(_class, "text-".concat(variant), variant), _defineProperty(_class, "b-icon-animation-".concat(animation), animation), _class), attrs: BASE_ATTRS, style: stacked ? {} : { fontSize: fontScale === 1 ? null : "".concat(fontScale * 100, "%") } }, // Merge in user supplied data data, // If icon is stacked, null-out some attrs stacked ? { attrs: STACKED_ATTRS } : {}, // These cannot be overridden by users { attrs: { xmlns: stacked ? null : 'http://www.w3.org/2000/svg', fill: 'currentColor' } }), $content); } }); /** * 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 kebabName = kebabCase(name); var iconName = "BIcon".concat(pascalCase(name)); var iconNameClass = "bi-".concat(kebabName); var iconTitle = kebabName.replace(/-/g, ' '); var svgContent = trim(content || ''); return /*#__PURE__*/Vue__default['default'].extend({ name: iconName, functional: true, props: omit(props$4, ['content']), render: function render(h, _ref) { var data = _ref.data, props = _ref.props; return h(BVIconBase, a( // Defaults { props: { title: iconTitle }, attrs: { 'aria-label': iconTitle } }, // User data data, // Required data { staticClass: iconNameClass, props: _objectSpread2(_objectSpread2({}, props), {}, { content: svgContent }) })); } }); }; // --- BEGIN AUTO-GENERATED FILE --- var BIconBlank=/*#__PURE__*/makeIcon('Blank','');// --- Bootstrap Icons --- var BIconCalendar=/*#__PURE__*/makeIcon('Calendar','<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>');// eslint-disable-next-line var BIconCalendarFill=/*#__PURE__*/makeIcon('CalendarFill','<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V5h16V4H0V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5z"/>');// eslint-disable-next-line var BIconChevronBarLeft=/*#__PURE__*/makeIcon('ChevronBarLeft','<path fill-rule="evenodd" d="M11.854 3.646a.5.5 0 0 1 0 .708L8.207 8l3.647 3.646a.5.5 0 0 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 0 1 .708 0zM4.5 1a.5.5 0 0 0-.5.5v13a.5.5 0 0 0 1 0v-13a.5.5 0 0 0-.5-.5z"/>');// eslint-disable-next-line var BIconChevronDoubleLeft=/*#__PURE__*/makeIcon('ChevronDoubleLeft','<path fill-rule="evenodd" d="M8.354 1.646a.5.5 0 0 1 0 .708L2.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/><path fill-rule="evenodd" d="M12.354 1.646a.5.5 0 0 1 0 .708L6.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>');// eslint-disable-next-line var BIconChevronDown=/*#__PURE__*/makeIcon('ChevronDown','<path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/>');// eslint-disable-next-line var BIconChevronLeft=/*#__PURE__*/makeIcon('ChevronLeft','<path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>');// eslint-disable-next-line var BIconChevronUp=/*#__PURE__*/makeIcon('ChevronUp','<path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708l6-6z"/>');// eslint-disable-next-line var BIconCircleFill=/*#__PURE__*/makeIcon('CircleFill','<circle cx="8" cy="8" r="8"/>');// eslint-disable-next-line var BIconClock=/*#__PURE__*/makeIcon('Clock','<path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z"/><path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z"/>');// eslint-disable-next-line var BIconClockFill=/*#__PURE__*/makeIcon('ClockFill','<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z"/>');// eslint-disable-next-line var BIconDash=/*#__PURE__*/makeIcon('Dash','<path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"/>');// eslint-disable-next-line var BIconPersonFill=/*#__PURE__*/makeIcon('PersonFill','<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>');// eslint-disable-next-line var BIconPlus=/*#__PURE__*/makeIcon('Plus','<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>');// eslint-disable-next-line var BIconStar=/*#__PURE__*/makeIcon('Star','<path d="M2.866 14.85c-.078.444.36.791.746.593l4.39-2.256 4.389 2.256c.386.198.824-.149.746-.592l-.83-4.73 3.523-3.356c.329-.314.158-.888-.283-.95l-4.898-.696L8.465.792a.513.513 0 0 0-.927 0L5.354 5.12l-4.898.696c-.441.062-.612.636-.283.95l3.523 3.356-.83 4.73zm4.905-2.767l-3.686 1.894.694-3.957a.565.565 0 0 0-.163-.505L1.71 6.745l4.052-.576a.525.525 0 0 0 .393-.288l1.847-3.658 1.846 3.658a.525.525 0 0 0 .393.288l4.052.575-2.906 2.77a.564.564 0 0 0-.163.506l.694 3.957-3.686-1.894a.503.503 0 0 0-.461 0z"/>');// eslint-disable-next-line var BIconStarFill=/*#__PURE__*/makeIcon('StarFill','<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.283.95l-3.523 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>');// eslint-disable-next-line var BIconStarHalf=/*#__PURE__*/makeIcon('StarHalf','<path d="M5.354 5.119L7.538.792A.516.516 0 0 1 8 .5c.183 0 .366.097.465.292l2.184 4.327 4.898.696A.537.537 0 0 1 16 6.32a.55.55 0 0 1-.17.445l-3.523 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256a.519.519 0 0 1-.146.05c-.341.06-.668-.254-.6-.642l.83-4.73L.173 6.765a.55.55 0 0 1-.171-.403.59.59 0 0 1 .084-.302.513.513 0 0 1 .37-.245l4.898-.696zM8 12.027c.08 0 .16.018.232.056l3.686 1.894-.694-3.957a.564.564 0 0 1 .163-.505l2.906-2.77-4.052-.576a.525.525 0 0 1-.393-.288L8.002 2.223 8 2.226v9.8z"/>');// eslint-disable-next-line var BIconX=/*#__PURE__*/makeIcon('X','<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>');// eslint-disable-next-line // --- END AUTO-GENERATED FILE --- var findIconComponent = function findIconComponent(ctx, iconName) { if (!ctx) { return null; } var components = (ctx.$options || {}).components; var iconComponent = components[iconName]; return iconComponent || findIconComponent(ctx.$parent, iconName); }; // --- Props --- var iconProps = omit(props$4, ['content']); var props$5 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, iconProps), {}, { icon: makeProp(PROP_TYPE_STRING) })), NAME_ICON); // --- Main component --- // Helper BIcon component // Requires the requested icon component to be installed // @vue/component var BIcon = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_ICON, functional: true, props: props$5, 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, ''); // 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 return h(icon ? findIconComponent(parent, "BIcon".concat(icon)) || BIconBlank : BIconBlank, a(data, { props: pluckProps(iconProps, props) })); } }); var CODE_BACKSPACE = 8; var CODE_DELETE = 46; var CODE_DOWN = 40; var CODE_END = 35; var CODE_ENTER = 13; var CODE_ESC = 27; var CODE_HOME = 36; var CODE_LEFT = 37; var CODE_PAGEDOWN = 34; var CODE_PAGEUP = 33; var CODE_RIGHT = 39; var CODE_SPACE = 32; var CODE_UP = 38; // 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) { var aHasKey = hasOwnProperty(a, key); var bHasKey = hasOwnProperty(b, key); if (aHasKey && !bHasKey || !aHasKey && bHasKey || !looseEqual(a[key], b[key])) { return false; } } } return String(a) === String(b); }; var isEmpty = function isEmpty(value) { return !value || keys(value).length === 0; }; var makePropWatcher = function makePropWatcher(propName) { return { handler: function handler(newValue, oldValue) { if (looseEqual(newValue, oldValue)) { return; } if (isEmpty(newValue) || isEmpty(oldValue)) { this[propName] = cloneDeep(newValue); return; } for (var key in oldValue) { if (!hasOwnProperty(newValue, key)) { this.$delete(this.$data[propName], key); } } for (var _key in newValue) { this.$set(this.$data[propName], _key, newValue[_key]); } } }; }; var makePropCacheMixin = function makePropCacheMixin(propName, proxyPropName) { return Vue__default['default'].extend({ data: function data() { return _defineProperty({}, proxyPropName, cloneDeep(this[propName])); }, watch: _defineProperty({}, propName, makePropWatcher(proxyPropName)) }); }; var attrsMixin = makePropCacheMixin('$attrs', 'bvAttrs'); var listenOnRootMixin = Vue__default['default'].extend({ 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 */ listenOnRoot: function listenOnRoot(event, callback) { var _this = this; this.$root.$on(event, callback); this.$on(HOOK_EVENT_NAME_BEFORE_DESTROY, function () { _this.$root.$off(event, callback); }); }, /** * 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 */ listenOnRootOnce: function listenOnRootOnce(event, callback) { var _this2 = this; this.$root.$once(event, callback); this.$on(HOOK_EVENT_NAME_BEFORE_DESTROY, function () { _this2.$root.$off(event, callback); }); }, /** * Convenience method for calling `vm.$emit()` on `vm.$root` * * @param {string} event * @param {*} args */ 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)); } } }); var listenersMixin = makePropCacheMixin('$listeners', 'bvListeners'); var ROOT_EVENT_NAME_CLICKED = getRootEventName(NAME_LINK, 'clicked'); // --- Props --- // `<router-link>` specific props var routerLinkProps = { activeClass: makeProp(PROP_TYPE_STRING), append: makeProp(PROP_TYPE_BOOLEAN, false), event: makeProp(PROP_TYPE_ARRAY_STRING, EVENT_NAME_CLICK), exact: makeProp(PROP_TYPE_BOOLEAN, false), exactActiveClass: makeProp(PROP_TYPE_STRING), replace: makeProp(PROP_TYPE_BOOLEAN, false), routerTag: makeProp(PROP_TYPE_STRING, 'a'), to: makeProp(PROP_TYPE_OBJECT_STRING) }; // `<nuxt-link>` specific props var nuxtLinkProps = { noPrefetch: makeProp(PROP_TYPE_BOOLEAN, false), // Must be `null` to fall back to the value defined in the // `nuxt.config.js` configuration file for `router.prefetchLinks` // We convert `null` to `undefined`, so that Nuxt.js will use the // compiled default // Vue treats `undefined` as default of `false` for Boolean props, // so we must set it as `null` here to be a true tri-state prop prefetch: makeProp(PROP_TYPE_BOOLEAN, null) }; // All `<b-link>` props var props$6 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, nuxtLinkProps), routerLinkProps), {}, { active: makeProp(PROP_TYPE_BOOLEAN, false), disabled: makeProp(PROP_TYPE_BOOLEAN, false), href: makeProp(PROP_TYPE_STRING), // Must be `null` if no value provided rel: makeProp(PROP_TYPE_STRING, null), // To support 3rd party router links based on `<router-link>` (i.e. `g-link` for Gridsome) // Default is to auto choose between `<router-link>` and `<nuxt-link>` // Gridsome doesn't provide a mechanism to auto detect and has caveats // such as not supporting FQDN URLs or hash only URLs routerComponentName: makeProp(PROP_TYPE_STRING), target: makeProp(PROP_TYPE_STRING, '_self') })), NAME_LINK); // --- Main component --- // @vue/component var BLink = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_LINK, // Mixin order is important! mixins: [attrsMixin, listenersMixin, listenOnRootMixin, normalizeSlotMixin], inheritAttrs: false, props: props$6, computed: { computedTag: function computedTag() { // We don't pass `this` as the first arg as we need reactivity of the props var to = this.to, disabled = this.disabled, routerComponentName = this.routerComponentName; return computeTag({ to: to, disabled: disabled, routerComponentName: routerComponentName }, 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 var target = this.target, rel = this.rel; return computeRel({ target: target, rel: rel }); }, computedHref: function computedHref() { // We don't pass `this` as the first arg as we need reactivity of the props var to = this.to, href = this.href; return computeHref({ to: to, href: href }, this.computedTag); }, computedProps: function computedProps() { var prefetch = this.prefetch; return this.isRouterLink ? _objectSpread2(_objectSpread2({}, pluckProps(_objectSpread2(_objectSpread2({}, routerLinkProps), nuxtLinkProps), this)), {}, { // Coerce `prefetch` value `null` to be `undefined` prefetch: isBoolean(prefetch) ? prefetch : undefined, // Pass `router-tag` as `tag` prop tag: this.routerTag }) : {}; }, computedAttrs: function computedAttrs() { var bvAttrs = this.bvAttrs, href = this.computedHref, rel = this.computedRel, disabled = this.disabled, target = this.target, routerTag = this.routerTag, isRouterLink = this.isRouterLink; return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, bvAttrs), href ? { href: href } : {}), isRouterLink && !isTag(routerTag, 'a') ? {} : { rel: rel, target: target }), {}, { tabindex: disabled ? '-1' : isUndefined(bvAttrs.tabindex) ? null : bvAttrs.tabindex, 'aria-disabled': disabled ? 'true' : null }); }, computedListeners: function computedListeners() { return _objectSpread2(_objectSpread2({}, this.bvListeners), {}, { // We want to overwrite any click handler since our callback // will invoke the user supplied handler(s) if `!this.disabled` click: this.onClick }); } }, methods: { onClick: function onClick(event) { var _arguments = arguments; var eventIsEvent = isEvent(event); var isRouterLink = this.isRouterLink; var suppliedHandler = this.bvListeners.click; if (eventIsEvent && this.disabled) { // Stop event from bubbling up // Kill the event loop attached to this specific `EventTarget` // Needed to prevent `vue-router` for doing its thing stopEvent(event, { immediatePropagation: true }); } else { /* istanbul ignore next: difficult to test, but we know it works */ if (isRouterLink && event.currentTarget.__vue__) { // Router links do not emit instance `click` events, so we // add in an `$emit('click', event)` on its Vue instance event.currentTarget.__vue__.$emit(EVENT_NAME_CLICK, event); } // 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.emitOnRoot(ROOT_EVENT_NAME_CLICKED, event); // TODO: Remove deprecated 'clicked::link' event with next major release this.emitOnRoot('clicked::link', event); } // Stop scroll-to-top behavior or navigation on // regular links when href is just '#' if (eventIsEvent && !isRouterLink && this.computedHref === '#') { stopEvent(event, { propagation: false }); } }, focus: function focus() { attemptFocus(this.$el); }, blur: function blur() { attemptBlur(this.$el); } }, render: function render(h) { var active = this.active, disabled = this.disabled; return h(this.computedTag, _defineProperty({ class: { active: active, disabled: disabled }, attrs: this.computedAttrs, props: this.computedProps }, this.isRouterLink ? 'nativeOn' : 'on', this.computedListeners), this.normalizeSlot()); } }); var linkProps = omit(props$6, ['event', 'routerTag']); delete linkProps.href.default; delete linkProps.to.default; var props$7 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps), {}, { block: makeProp(PROP_TYPE_BOOLEAN, false), disabled: makeProp(PROP_TYPE_BOOLEAN, false), pill: makeProp(PROP_TYPE_BOOLEAN, false), // Tri-state: `true`, `false` or `null` // => On, off, not a toggle pressed: makeProp(PROP_TYPE_BOOLEAN, null), size: makeProp(PROP_TYPE_STRING), squared: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'button'), type: makeProp(PROP_TYPE_STRING, 'button'), variant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_BUTTON); // --- Helper methods --- // Focus handler for toggle buttons // Needs class of 'focus' when focused var handleFocus = function handleFocus(event) { if (event.type === 'focusin') { addClass(event.target, 'focus'); } else if (event.type === 'focusout') { removeClass(event.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$1 = function isLink$1(props) { return isLink(props) || isTag(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$1(props) || props.tag && !isTag(props.tag, 'button')); }; // Is the requested tag not a button or link? var isNonStandardTag = function isNonStandardTag(props) { return !isLink$1(props) && !isButton(props); }; // Compute required classes (non static classes) var computeClass = function computeClass(props) { var _ref; return ["btn-".concat(props.variant || 'secondary'), (_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$1(props) ? pluckProps(linkProps, props) : {}; }; // Compute the attributes for a button var computeAttrs = function computeAttrs(props, data) { var button = isButton(props); var link = isLink$1(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 }; }; // --- Main component --- // @vue/component var BButton = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BUTTON, functional: true, props: props$7, 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$1(props); var nonStandardTag = isNonStandardTag(props); var hashLink = link && props.href === '#'; var on = { keydown: function keydown(event) { // When the link is a `href="#"` or a non-standard tag (has `role="button"`), // we add a keydown handlers for CODE_SPACE/CODE_ENTER /* istanbul ignore next */ if (props.disabled || !(nonStandardTag || hashLink)) { return; } var keyCode = event.keyCode; // Add CODE_SPACE handler for `href="#"` and CODE_ENTER handler for non-standard tags if (keyCode === CODE_SPACE || keyCode === CODE_ENTER && nonStandardTag) { var target = event.currentTarget || event.target; stopEvent(event, { propagation: false }); target.click(); } }, click: function click(event) { /* istanbul ignore if: blink/button disabled should handle this */ if (props.disabled && isEvent(event)) { stopEvent(event); } 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 CLASS_NAME$1 = 'b-avatar'; var SIZES = ['sm', null, 'lg']; var FONT_SIZE_SCALE = 0.4; var BADGE_FONT_SIZE_SCALE = FONT_SIZE_SCALE * 0.7; // --- Helper methods --- var computeSize = function computeSize(value) { // Parse to number when value is a float-like string value = isString(value) && isNumeric(value) ? toFloat(value, 0) : value; // Convert all numbers to pixel values return isNumber(value) ? "".concat(value, "px") : value || null; }; // --- Props --- var linkProps$1 = omit(props$6, ['active', 'event', 'routerTag']); var props$8 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps$1), {}, { alt: makeProp(PROP_TYPE_STRING, 'avatar'), ariaLabel: makeProp(PROP_TYPE_STRING), badge: makeProp(PROP_TYPE_BOOLEAN_STRING, false), badgeLeft: makeProp(PROP_TYPE_BOOLEAN, false), badgeOffset: makeProp(PROP_TYPE_STRING), badgeTop: makeProp(PROP_TYPE_BOOLEAN, false), badgeVariant: makeProp(PROP_TYPE_STRING, 'primary'), button: makeProp(PROP_TYPE_BOOLEAN, false), buttonType: makeProp(PROP_TYPE_STRING, 'button'), icon: makeProp(PROP_TYPE_STRING), rounded: makeProp(PROP_TYPE_BOOLEAN_STRING, false), size: makeProp(PROP_TYPE_NUMBER_STRING), square: makeProp(PROP_TYPE_BOOLEAN, false), src: makeProp(PROP_TYPE_STRING), text: makeProp(PROP_TYPE_STRING), variant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_AVATAR); // --- Main component --- // @vue/component var BAvatar = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_AVATAR, mixins: [normalizeSlotMixin], inject: { bvAvatarGroup: { default: null } }, props: props$8, data: function data() { return { localSrc: this.src || null }; }, computed: { computedSize: function computedSize() { // Always use the avatar group size var bvAvatarGroup = this.bvAvatarGroup; return computeSize(bvAvatarGroup ? bvAvatarGroup.size : this.size); }, computedVariant: function computedVariant() { var bvAvatarGroup = this.bvAvatarGroup; return bvAvatarGroup && bvAvatarGroup.variant ? bvAvatarGroup.variant : this.variant; }, computedRounded: function computedRounded() { var bvAvatarGroup = this.bvAvatarGroup; var square = bvAvatarGroup && bvAvatarGroup.square ? true : this.square; var rounded = bvAvatarGroup && bvAvatarGroup.rounded ? bvAvatarGroup.rounded : this.rounded; return square ? '0' : rounded === '' ? true : rounded || 'circle'; }, fontStyle: function fontStyle() { var size = this.computedSize; var fontSize = SIZES.indexOf(size) === -1 ? "calc(".concat(size, " * ").concat(FONT_SIZE_SCALE, ")") : null; return fontSize ? { fontSize: fontSize } : {}; }, marginStyle: function marginStyle() { var size = this.computedSize, bvAvatarGroup = this.bvAvatarGroup; var overlapScale = bvAvatarGroup ? bvAvatarGroup.overlapScale : 0; var value = size && overlapScale ? "calc(".concat(size, " * -").concat(overlapScale, ")") : null; return value ? { marginLeft: value, marginRight: value } : {}; }, badgeStyle: function badgeStyle() { var size = this.computedSize, badgeTop = this.badgeTop, badgeLeft = this.badgeLeft, badgeOffset = this.badgeOffset; var offset = badgeOffset || '0px'; return { fontSize: SIZES.indexOf(size) === -1 ? "calc(".concat(size, " * ").concat(BADGE_FONT_SIZE_SCALE, " )") : null, top: badgeTop ? offset : null, bottom: badgeTop ? null : offset, left: badgeLeft ? offset : null, right: badgeLeft ? null : offset }; } }, watch: { src: function src(newValue, oldValue) { if (newValue !== oldValue) { this.localSrc = newValue || null; } } }, methods: { onImgError: function onImgError(event) { this.localSrc = null; this.$emit(EVENT_NAME_IMG_ERROR, event); }, onClick: function onClick(event) { this.$emit(EVENT_NAME_CLICK, event); } }, render: function render(h) { var _class2; var variant = this.computedVariant, disabled = this.disabled, rounded = this.computedRounded, icon = this.icon, src = this.localSrc, text = this.text, fontStyle = this.fontStyle, marginStyle = this.marginStyle, size = this.computedSize, button = this.button, type = this.buttonType, badge = this.badge, badgeVariant = this.badgeVariant, badgeStyle = this.badgeStyle; var link = !button && isLink(this); var tag = button ? BButton : link ? BLink : 'span'; var alt = this.alt; var ariaLabel = this.ariaLabel || null; var $content = null; if (this.hasNormalizedSlot()) { // Default slot overrides props $content = h('span', { staticClass: 'b-avatar-custom' }, [this.normalizeSlot()]); } else if (src) { $content = h('img', { style: variant ? {} : { width: '100%', height: '100%' }, attrs: { src: src, alt: alt }, on: { error: this.onImgError } }); $content = h('span', { staticClass: 'b-avatar-img' }, [$content]); } else if (icon) { $content = h(BIcon, { props: { icon: icon }, attrs: { 'aria-hidden': 'true', alt: alt } }); } else if (text) { $content = h('span', { staticClass: 'b-avatar-text', style: fontStyle }, [h('span', text)]); } else { // Fallback default avatar content $content = h(BIconPersonFill, { attrs: { 'aria-hidden': 'true', alt: alt } }); } var $badge = h(); var hasBadgeSlot = this.hasNormalizedSlot(SLOT_NAME_BADGE); if (badge || badge === '' || hasBadgeSlot) { var badgeText = badge === true ? '' : badge; $badge = h('span', { staticClass: 'b-avatar-badge', class: _defineProperty({}, "badge-".concat(badgeVariant), badgeVariant), style: badgeStyle }, [hasBadgeSlot ? this.normalizeSlot(SLOT_NAME_BADGE) : badgeText]); } var componentData = { staticClass: CLASS_NAME$1, class: (_class2 = {}, _defineProperty(_class2, "".concat(CLASS_NAME$1, "-").concat(size), size && SIZES.indexOf(size) !== -1), _defineProperty(_class2, "badge-".concat(variant), !button && variant), _defineProperty(_class2, "rounded", rounded === true), _defineProperty(_class2, "rounded-".concat(rounded), rounded && rounded !== true), _defineProperty(_class2, "disabled", disabled), _class2), style: _objectSpread2(_objectSpread2({}, marginStyle), {}, { width: size, height: size }), attrs: { 'aria-label': ariaLabel || null }, props: button ? { variant: variant, disabled: disabled, type: type } : link ? pluckProps(linkProps$1, this) : {}, on: button || link ? { click: this.onClick } : {} }; return h(tag, componentData, [$content, $badge]); } }); var props$9 = makePropsConfigurable({ overlap: makeProp(PROP_TYPE_NUMBER_STRING, 0.3), // Child avatars will prefer this prop (if set) over their own rounded: makeProp(PROP_TYPE_BOOLEAN_STRING, false), // Child avatars will always use this over their own size size: makeProp(PROP_TYPE_STRING), // Child avatars will prefer this prop (if set) over their own square: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div'), // Child avatars will prefer this variant over their own variant: makeProp(PROP_TYPE_STRING) }, NAME_AVATAR_GROUP); // --- Main component --- // @vue/component var BAvatarGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_AVATAR_GROUP, mixins: [normalizeSlotMixin], provide: function provide() { return { bvAvatarGroup: this }; }, props: props$9, computed: { computedSize: function computedSize() { return computeSize(this.size); }, overlapScale: function overlapScale() { return mathMin(mathMax(toFloat(this.overlap, 0), 0), 1) / 2; }, paddingStyle: function paddingStyle() { var value = this.computedSize; value = value ? "calc(".concat(value, " * ").concat(this.overlapScale, ")") : null; return value ? { paddingLeft: value, paddingRight: value } : {}; } }, render: function render(h) { var $inner = h('div', { staticClass: 'b-avatar-group-inner', style: this.paddingStyle }, this.normalizeSlot()); return h(this.tag, { staticClass: 'b-avatar-group', attrs: { role: 'group' } }, [$inner]); } }); var AvatarPlugin = /*#__PURE__*/pluginFactory({ components: { BAvatar: BAvatar, BAvatarGroup: BAvatarGroup } }); var linkProps$2 = omit(props$6, ['event', 'routerTag']); delete linkProps$2.href.default; delete linkProps$2.to.default; var props$a = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps$2), {}, { pill: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'span'), variant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_BADGE); // --- Main component --- // @vue/component var BBadge = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BADGE, functional: true, props: props$a, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var active = props.active, disabled = props.disabled; var link = isLink(props); var tag = link ? BLink : props.tag; var variant = props.variant || 'secondary'; return h(tag, a(data, { staticClass: 'badge', class: ["badge-".concat(variant), { 'badge-pill': props.pill, active: active, disabled: disabled }], props: link ? pluckProps(linkProps$2, props) : {} }), children); } }); var BadgePlugin = /*#__PURE__*/pluginFactory({ components: { BBadge: BBadge } }); var stripTags = function stripTags() { var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; return String(text).replace(RX_HTML_TAGS, ''); }; // Generate a `domProps` object for either `innerHTML`, `textContent` or an empty object var htmlOrText = function htmlOrText(innerHTML, textContent) { return innerHTML ? { innerHTML: innerHTML } : textContent ? { textContent: textContent } : {}; }; var props$b = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, omit(props$6, ['event', 'routerTag'])), {}, { ariaCurrent: makeProp(PROP_TYPE_STRING, 'location'), html: makeProp(PROP_TYPE_STRING), text: makeProp(PROP_TYPE_STRING) })), NAME_BREADCRUMB_LINK); // --- Main component --- // @vue/component var BBreadcrumbLink = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BREADCRUMB_LINK, functional: true, props: props$b, render: function render(h, _ref) { var suppliedProps = _ref.props, data = _ref.data, children = _ref.children; var active = suppliedProps.active; var tag = active ? 'span' : BLink; var componentData = { attrs: { 'aria-current': active ? suppliedProps.ariaCurrent : null }, props: pluckProps(props$b, suppliedProps) }; if (!children) { componentData.domProps = htmlOrText(suppliedProps.html, suppliedProps.text); } return h(tag, a(data, componentData), children); } }); var props$c = makePropsConfigurable(props$b, NAME_BREADCRUMB_ITEM); // --- Main component --- // @vue/component var BBreadcrumbItem = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BREADCRUMB_ITEM, functional: true, props: props$c, 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$d = makePropsConfigurable({ items: makeProp(PROP_TYPE_ARRAY) }, NAME_BREADCRUMB); // --- Main component --- // @vue/component var BBreadcrumb = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BREADCRUMB, functional: true, props: props$d, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var items = props.items; // Build child nodes from items, if given var childNodes = children; if (isArray(items)) { var activeDefined = false; childNodes = items.map(function (item, idx) { if (!isObject(item)) { item = { text: toString$1(item) }; } // Copy the value here so we can normalize it var _item = item, active = _item.active; if (active) { activeDefined = true; } // Auto-detect active by position in list if (!active && !activeDefined) { active = idx + 1 === items.length; } return h(BBreadcrumbItem, { props: _objectSpread2(_objectSpread2({}, item), {}, { active: active }) }); }); } return h('ol', a(data, { staticClass: 'breadcrumb' }), childNodes); } }); var BreadcrumbPlugin = /*#__PURE__*/pluginFactory({ components: { BBreadcrumb: BBreadcrumb, BBreadcrumbItem: BBreadcrumbItem, BBreadcrumbLink: BBreadcrumbLink } }); var ButtonPlugin = /*#__PURE__*/pluginFactory({ components: { BButton: BButton, BBtn: BButton, BButtonClose: BButtonClose, BBtnClose: BButtonClose } }); var props$e = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, pick(props$7, ['size'])), {}, { ariaRole: makeProp(PROP_TYPE_STRING, 'group'), size: makeProp(PROP_TYPE_STRING), tag: makeProp(PROP_TYPE_STRING, 'div'), vertical: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_BUTTON_GROUP); // --- Main component --- // @vue/component var BButtonGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BUTTON_GROUP, 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, { 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(','); // --- Props --- var props$f = makePropsConfigurable({ justify: makeProp(PROP_TYPE_BOOLEAN, false), keyNav: makeProp(PROP_TYPE_BOOLEAN, false) }, NAME_BUTTON_TOOLBAR); // --- Main component --- // @vue/component var BButtonToolbar = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_BUTTON_TOOLBAR, mixins: [normalizeSlotMixin], props: props$f, mounted: function mounted() { // Pre-set the tabindexes if the markup does not include // `tabindex="-1"` on the toolbar items if (this.keyNav) { this.getItems(); } }, methods: { getItems: function getItems() { var items = selectAll(ITEM_SELECTOR, this.$el); // Ensure `tabindex="-1"` is set on every item items.forEach(function (item) { item.tabIndex = -1; }); return items.filter(function (el) { return isVisible(el); }); }, focusFirst: function focusFirst() { var items = this.getItems(); attemptFocus(items[0]); }, focusPrev: function focusPrev(event) { var items = this.getItems(); var index = items.indexOf(event.target); if (index > -1) { items = items.slice(0, index).reverse(); attemptFocus(items[0]); } }, focusNext: function focusNext(event) { var items = this.getItems(); var index = items.indexOf(event.target); if (index > -1) { items = items.slice(index + 1); attemptFocus(items[0]); } }, focusLast: function focusLast() { var items = this.getItems().reverse(); attemptFocus(items[0]); }, onFocusin: function onFocusin(event) { var $el = this.$el; if (event.target === $el && !contains($el, event.relatedTarget)) { stopEvent(event); this.focusFirst(event); } }, onKeydown: function onKeydown(event) { var keyCode = event.keyCode, shiftKey = event.shiftKey; if (keyCode === CODE_UP || keyCode === CODE_LEFT) { stopEvent(event); shiftKey ? this.focusFirst(event) : this.focusPrev(event); } else if (keyCode === CODE_DOWN || keyCode === CODE_RIGHT) { stopEvent(event); shiftKey ? this.focusLast(event) : this.focusNext(event); } } }, render: function render(h) { var keyNav = this.keyNav; return h('div', { staticClass: 'btn-toolbar', class: { 'justify-content-between': this.justify }, attrs: { role: 'toolbar', tabindex: keyNav ? '0' : null }, on: keyNav ? { focusin: this.onFocusin, keydown: this.onKeydown } : {} }, [this.normalizeSlot()]); } }); var ButtonToolbarPlugin = /*#__PURE__*/pluginFactory({ components: { BButtonToolbar: BButtonToolbar, BBtnToolbar: BButtonToolbar } }); var CALENDAR_GREGORY = 'gregory'; var CALENDAR_LONG = 'long'; var CALENDAR_NARROW = 'narrow'; var CALENDAR_SHORT = 'short'; var DATE_FORMAT_2_DIGIT = '2-digit'; var DATE_FORMAT_NUMERIC = 'numeric'; // 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(RX_DATE_SPLIT).map(function (v) { return toInteger(v, 1); }), _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] : CALENDAR_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 addYears = function addYears(date, numberOfYears) { date = createDate(date); var month = date.getMonth(); date.setFullYear(date.getFullYear() + numberOfYears); // Handle Feb 29th for leap years if (date.getMonth() !== month) { date.setDate(0); } return date; }; var oneMonthAgo = function oneMonthAgo(date) { date = createDate(date); var month = date.getMonth(); date.setMonth(month - 1); // Handle when days in month are different 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); // Handle when days in month are different if (date.getMonth() === (month + 2) % 12) { date.setDate(0); } return date; }; var oneYearAgo = function oneYearAgo(date) { return addYears(date, -1); }; var oneYearAhead = function oneYearAhead(date) { return addYears(date, 1); }; var oneDecadeAgo = function oneDecadeAgo(date) { return addYears(date, -10); }; var oneDecadeAhead = function oneDecadeAhead(date) { return addYears(date, 10); }; // Helper function to constrain a date between two values // Always returns a `Date` object or `null` if no date passed var constrainDate = function constrainDate(date) { var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; // Ensure values are `Date` objects (or `null`) date = parseYMD(date); min = parseYMD(min) || date; max = parseYMD(max) || date; // Return a new `Date` object (or `null`) return date ? date < min ? min : date > max ? max : date : null; }; // 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(); }); // 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_LOCALE_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 var props$g = { id: makeProp(PROP_TYPE_STRING) }; // --- Mixin --- // @vue/component var idMixin = Vue__default['default'].extend({ props: props$g, 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 regenerates 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-generated ID after mount // to prevent SSR hydration errors _this.localId_ = "__BVID__".concat(_this[COMPONENT_UID_KEY]); }); } }); var _watch$1; var _makeModelMixin$1 = makeModelMixin('value', { type: PROP_TYPE_DATE_STRING }), modelMixin$1 = _makeModelMixin$1.mixin, modelProps$1 = _makeModelMixin$1.props, MODEL_PROP_NAME$1 = _makeModelMixin$1.prop, MODEL_EVENT_NAME$1 = _makeModelMixin$1.event; // --- Props --- var props$h = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$1), {}, { ariaControls: makeProp(PROP_TYPE_STRING), // Makes calendar the full width of its parent container block: makeProp(PROP_TYPE_BOOLEAN, false), dateDisabledFn: makeProp(PROP_TYPE_FUNCTION), // `Intl.DateTimeFormat` object dateFormatOptions: makeProp(PROP_TYPE_OBJECT, { year: DATE_FORMAT_NUMERIC, month: CALENDAR_LONG, day: DATE_FORMAT_NUMERIC, weekday: CALENDAR_LONG }), // 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 dateInfoFn: makeProp(PROP_TYPE_FUNCTION), // 'ltr', 'rtl', or `null` (for auto detect) direction: makeProp(PROP_TYPE_STRING), disabled: makeProp(PROP_TYPE_BOOLEAN, false), // 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) hidden: makeProp(PROP_TYPE_BOOLEAN, false), // When `true` makes the selected date header `sr-only` hideHeader: makeProp(PROP_TYPE_BOOLEAN, false), // This specifies the calendar year/month/day that will be shown when // first opening the datepicker if no v-model value is provided // Default is the current date (or `min`/`max`) initialDate: makeProp(PROP_TYPE_DATE_STRING), // Labels for buttons and keyboard shortcuts labelCalendar: makeProp(PROP_TYPE_STRING, 'Calendar'), labelCurrentMonth: makeProp(PROP_TYPE_STRING, 'Current month'), labelHelp: makeProp(PROP_TYPE_STRING, 'Use cursor keys to navigate calendar dates'), labelNav: makeProp(PROP_TYPE_STRING, 'Calendar navigation'), labelNextDecade: makeProp(PROP_TYPE_STRING, 'Next decade'), labelNextMonth: makeProp(PROP_TYPE_STRING, 'Next month'), labelNextYear: makeProp(PROP_TYPE_STRING, 'Next year'), labelNoDateSelected: makeProp(PROP_TYPE_STRING, 'No date selected'), labelPrevDecade: makeProp(PROP_TYPE_STRING, 'Previous decade'), labelPrevMonth: makeProp(PROP_TYPE_STRING, 'Previous month'), labelPrevYear: makeProp(PROP_TYPE_STRING, 'Previous year'), labelSelected: makeProp(PROP_TYPE_STRING, 'Selected date'), labelToday: makeProp(PROP_TYPE_STRING, 'Today'), // Locale(s) to use // Default is to use page/browser default setting locale: makeProp(PROP_TYPE_ARRAY_STRING), max: makeProp(PROP_TYPE_DATE_STRING), min: makeProp(PROP_TYPE_DATE_STRING), // Variant color to use for the navigation buttons navButtonVariant: makeProp(PROP_TYPE_STRING, 'secondary'), // Disable highlighting today's date noHighlightToday: makeProp(PROP_TYPE_BOOLEAN, false), noKeyNav: makeProp(PROP_TYPE_BOOLEAN, false), readonly: makeProp(PROP_TYPE_BOOLEAN, false), roleDescription: makeProp(PROP_TYPE_STRING), // Variant color to use for the selected date selectedVariant: makeProp(PROP_TYPE_STRING, 'primary'), // When `true` enables the decade navigation buttons showDecadeNav: makeProp(PROP_TYPE_BOOLEAN, false), // Day of week to start calendar on // `0` (Sunday), `1` (Monday), ... `6` (Saturday) startWeekday: makeProp(PROP_TYPE_NUMBER_STRING, 0), // Variant color to use for today's date (defaults to `selectedVariant`) todayVariant: makeProp(PROP_TYPE_STRING), // Always return the `v-model` value as a date object valueAsDate: makeProp(PROP_TYPE_BOOLEAN, false), // Format of the weekday names at the top of the calendar // `short` is typically a 3 letter abbreviation, // `narrow` is typically a single letter // `long` is the full week day name // Although some locales may override this (i.e `ar`, etc.) weekdayHeaderFormat: makeProp(PROP_TYPE_STRING, CALENDAR_SHORT, function (value) { return arrayIncludes([CALENDAR_LONG, CALENDAR_SHORT, CALENDAR_NARROW], value); }), // Has no effect if prop `block` is set width: makeProp(PROP_TYPE_STRING, '270px') })), NAME_CALENDAR); // --- Main component --- // @vue/component var BCalendar = Vue__default['default'].extend({ name: NAME_CALENDAR, // Mixin order is important! mixins: [attrsMixin, idMixin, modelMixin$1, normalizeSlotMixin], props: props$h, data: function data() { var selected = formatYMD(this[MODEL_PROP_NAME$1]) || ''; return { // Selected date selectedYMD: selected, // Date in calendar grid that has `tabindex` of `0` activeYMD: selected || formatYMD(constrainDate(this.initialDate || this.getToday()), this.min, this.max), // 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: { valueId: function valueId() { return this.safeId(); }, widgetId: function widgetId() { return this.safeId('_calendar-wrapper_'); }, navId: function navId() { return this.safeId('_calendar-nav_'); }, gridId: function gridId() { return this.safeId('_calendar-grid_'); }, gridCaptionId: function gridCaptionId() { return this.safeId('_calendar-grid-caption_'); }, gridHelpId: function gridHelpId() { return this.safeId('_calendar-grid-help_'); }, activeId: function activeId() { return this.activeYMD ? this.safeId("_cell-".concat(this.activeYMD, "_")) : null; }, // 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 mathMax(toInteger(this.startWeekday, 0), 0) % 7; }, computedLocale: function computedLocale() { // Returns the resolved locale used by the calendar return resolveLocale(concat(this.locale).filter(identity), CALENDAR_GREGORY); }, computedDateDisabledFn: function computedDateDisabledFn() { var dateDisabledFn = this.dateDisabledFn; return hasPropFunction(dateDisabledFn) ? dateDisabledFn : function () { return false; }; }, // TODO: Change `dateInfoFn` to handle events and notes as well as classes computedDateInfoFn: function computedDateInfoFn() { var dateInfoFn = this.dateInfoFn; return hasPropFunction(dateInfoFn) ? dateInfoFn : function () { return {}; }; }, 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: 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 !== 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() { // We set the time for this date to 12pm to work around // date formatting issues in Firefox and Safari // See: https://github.com/bootstrap-vue/bootstrap-vue/issues/5818 return createDate(this.calendarYear, this.calendarMonth, 1, 12); }, 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'); }, computedNavButtonVariant: function computedNavButtonVariant() { return "btn-outline-".concat(this.navButtonVariant || '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, activeYMD = this.activeYMD; var selectedDate = parseYMD(selectedYMD); 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 whether 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, 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() { var _this = this; // 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; // 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) || _this.computedDateDisabledFn(ymd, date)); }; }, // Computed props that return date formatter functions formatDateString: function formatDateString() { // Returns a date formatter function return createDateFormatter(this.calendarLocale, _objectSpread2(_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: DATE_FORMAT_NUMERIC, month: DATE_FORMAT_2_DIGIT, day: DATE_FORMAT_2_DIGIT }, this.dateFormatOptions), {}, { // Ensure hours/minutes/seconds are not shown // As we do not support the time portion (yet) hour: undefined, minute: undefined, second: undefined, // Ensure calendar is gregorian calendar: CALENDAR_GREGORY })); }, formatYearMonth: function formatYearMonth() { // Returns a date formatter function return createDateFormatter(this.calendarLocale, { year: DATE_FORMAT_NUMERIC, month: CALENDAR_LONG, calendar: CALENDAR_GREGORY }); }, formatWeekdayName: function formatWeekdayName() { // Long weekday name for weekday header aria-label return createDateFormatter(this.calendarLocale, { weekday: CALENDAR_LONG, calendar: CALENDAR_GREGORY }); }, formatWeekdayNameShort: function formatWeekdayNameShort() { // Weekday header cell format // defaults to 'short' 3 letter days, where possible return createDateFormatter(this.calendarLocale, { weekday: this.weekdayHeaderFormat || CALENDAR_SHORT, calendar: CALENDAR_GREGORY }); }, formatDay: function formatDay() { // Calendar grid day number formatter // We don't use DateTimeFormatter here as it can place extra // character(s) after the number (i.e the `zh` locale) var nf = new Intl.NumberFormat([this.computedLocale], { style: 'decimal', minimumIntegerDigits: 1, minimumFractionDigits: 0, maximumFractionDigits: 0, notation: 'standard' }); // Return a formatter function instance return function (date) { return nf.format(date.getDate()); }; }, // Disabled states for the nav buttons prevDecadeDisabled: function prevDecadeDisabled() { var min = this.computedMin; return this.disabled || min && lastDateOfMonth(oneDecadeAgo(this.activeDate)) < min; }, 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; }, nextDecadeDisabled: function nextDecadeDisabled() { var max = this.computedMax; return this.disabled || max && firstDateOfMonth(oneDecadeAhead(this.activeDate)) > max; }, // Calendar dates 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; // 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 = this.computedDateInfoFn(dayYMD, parseYMD(dayYMD)); dateInfo = isString(dateInfo) || isArray(dateInfo) ? /* istanbul ignore next */ { class: dateInfo } : isPlainObject(dateInfo) ? _objectSpread2({ class: '' }, dateInfo) : /* istanbul ignore next */ { 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 _this2 = this; return this.calendar[0].map(function (d) { return { text: _this2.formatWeekdayNameShort(parseYMD(d.ymd)), label: _this2.formatWeekdayName(parseYMD(d.ymd)) }; }); } }, watch: (_watch$1 = {}, _defineProperty(_watch$1, MODEL_PROP_NAME$1, function (newValue, oldValue) { var selected = formatYMD(newValue) || ''; var old = formatYMD(oldValue) || ''; if (!datesEqual(selected, old)) { this.activeYMD = selected || this.activeYMD; this.selectedYMD = selected; } }), _defineProperty(_watch$1, "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(MODEL_EVENT_NAME$1, this.valueAsDate ? parseYMD(newYMD) || null : newYMD || ''); } }), _defineProperty(_watch$1, "context", function context(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(EVENT_NAME_CONTEXT, newValue); } }), _defineProperty(_watch$1, "hidden", function hidden(newValue) { // Reset the active focused day when hidden this.activeYMD = this.selectedYMD || formatYMD(this[MODEL_PROP_NAME$1] || this.constrainDate(this.initialDate || this.getToday())); // Enable/disable the live regions this.setLive(!newValue); }), _watch$1), created: function created() { var _this3 = this; this.$nextTick(function () { _this3.$emit(EVENT_NAME_CONTEXT, _this3.context); }); }, mounted: function mounted() { this.setLive(true); }, /* istanbul ignore next */ activated: function activated() { this.setLive(true); }, /* istanbul ignore next */ deactivated: function deactivated() { this.setLive(false); }, beforeDestroy: function beforeDestroy() { this.setLive(false); }, methods: { // Public method(s) focus: function focus() { if (!this.disabled) { attemptFocus(this.$refs.grid); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$refs.grid); } }, // Private methods setLive: function setLive(on) { var _this4 = this; if (on) { this.$nextTick(function () { requestAF(function () { _this4.isLive = true; }); }); } else { this.isLive = false; } }, getToday: function getToday() { return parseYMD(createDate()); }, constrainDate: function constrainDate$1(date) { // Constrains a date between min and max // returns a new `Date` object instance return constrainDate(date, this.computedMin, this.computedMax); }, emitSelected: function emitSelected(date) { var _this5 = this; // Performed in a `$nextTick()` to (probably) ensure // the input event has emitted first this.$nextTick(function () { _this5.$emit(EVENT_NAME_SELECTED, formatYMD(date) || '', parseYMD(date) || null); }); }, // Event handlers setGridFocusFlag: function setGridFocusFlag(event) { // Sets the gridHasFocus flag to make date "button" look focused this.gridHasFocus = !this.disabled && event.type === 'focus'; }, onKeydownWrapper: function onKeydownWrapper(event) { // Calendar keyboard navigation // Handles PAGEUP/PAGEDOWN/END/HOME/LEFT/UP/RIGHT/DOWN // Focuses grid after updating if (this.noKeyNav) { /* istanbul ignore next */ return; } var altKey = event.altKey, ctrlKey = event.ctrlKey, keyCode = event.keyCode; if (!arrayIncludes([CODE_PAGEUP, CODE_PAGEDOWN, CODE_END, CODE_HOME, CODE_LEFT, CODE_UP, CODE_RIGHT, CODE_DOWN], keyCode)) { /* istanbul ignore next */ return; } stopEvent(event); var activeDate = createDate(this.activeDate); var checkDate = createDate(this.activeDate); var day = activeDate.getDate(); var constrainedToday = this.constrainDate(this.getToday()); var isRTL = this.isRTL; if (keyCode === CODE_PAGEUP) { // PAGEUP - Previous month/year activeDate = (altKey ? ctrlKey ? oneDecadeAgo : oneYearAgo : oneMonthAgo)(activeDate); // We check the first day of month to be in rage checkDate = createDate(activeDate); checkDate.setDate(1); } else if (keyCode === CODE_PAGEDOWN) { // PAGEDOWN - Next month/year activeDate = (altKey ? ctrlKey ? oneDecadeAhead : 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 === CODE_LEFT) { // LEFT - Previous day (or next day for RTL) activeDate.setDate(day + (isRTL ? 1 : -1)); activeDate = this.constrainDate(activeDate); checkDate = activeDate; } else if (keyCode === CODE_RIGHT) { // RIGHT - Next day (or previous day for RTL) activeDate.setDate(day + (isRTL ? -1 : 1)); activeDate = this.constrainDate(activeDate); checkDate = activeDate; } else if (keyCode === CODE_UP) { // UP - Previous week activeDate.setDate(day - 7); activeDate = this.constrainDate(activeDate); checkDate = activeDate; } else if (keyCode === CODE_DOWN) { // DOWN - Next week activeDate.setDate(day + 7); activeDate = this.constrainDate(activeDate); checkDate = activeDate; } else if (keyCode === CODE_HOME) { // HOME - Today activeDate = constrainedToday; checkDate = activeDate; } else if (keyCode === CODE_END) { // END - Selected date, or today if no selected date activeDate = parseYMD(this.selectedDate) || constrainedToday; 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(event) { // Pressing enter/space on grid to select active date var keyCode = event.keyCode; var activeDate = this.activeDate; if (keyCode === CODE_ENTER || keyCode === CODE_SPACE) { stopEvent(event); 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, 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(); } }, gotoPrevDecade: function gotoPrevDecade() { this.activeYMD = formatYMD(this.constrainDate(oneDecadeAgo(this.activeDate))); }, 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.constrainDate(this.getToday())); }, gotoNextMonth: function gotoNextMonth() { this.activeYMD = formatYMD(this.constrainDate(oneMonthAhead(this.activeDate))); }, gotoNextYear: function gotoNextYear() { this.activeYMD = formatYMD(this.constrainDate(oneYearAhead(this.activeDate))); }, gotoNextDecade: function gotoNextDecade() { this.activeYMD = formatYMD(this.constrainDate(oneDecadeAhead(this.activeDate))); }, onHeaderClick: function onHeaderClick() { if (!this.disabled) { this.activeYMD = this.selectedYMD || formatYMD(this.getToday()); this.focus(); } } }, render: function render(h) { var _this6 = this; // If `hidden` prop is set, render just a placeholder node if (this.hidden) { return h(); } var valueId = this.valueId, widgetId = this.widgetId, navId = this.navId, gridId = this.gridId, gridCaptionId = this.gridCaptionId, gridHelpId = this.gridHelpId, activeId = this.activeId, disabled = this.disabled, noKeyNav = this.noKeyNav, isLive = this.isLive, isRTL = this.isRTL, activeYMD = this.activeYMD, selectedYMD = this.selectedYMD, safeId = this.safeId; var hideDecadeNav = !this.showDecadeNav; var todayYMD = formatYMD(this.getToday()); var highlightToday = !this.noHighlightToday; // Header showing current selected date var $header = h('output', { staticClass: 'form-control form-control-sm text-center', class: { 'text-muted': disabled, readonly: this.readonly || disabled }, attrs: { id: valueId, for: gridId, role: 'status', tabindex: 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" // ' ' ); $header = h('header', { staticClass: 'b-calendar-header', class: { 'sr-only': this.hideHeader }, attrs: { title: this.selectedDate ? this.labelSelectedDate || null : null } }, [$header]); // Content for the date navigation buttons var navScope = { isRTL: isRTL }; var navProps = { shiftV: 0.5 }; var navPrevProps = _objectSpread2(_objectSpread2({}, navProps), {}, { flipH: isRTL }); var navNextProps = _objectSpread2(_objectSpread2({}, navProps), {}, { flipH: !isRTL }); var $prevDecadeIcon = this.normalizeSlot(SLOT_NAME_NAV_PEV_DECADE, navScope) || h(BIconChevronBarLeft, { props: navPrevProps }); var $prevYearIcon = this.normalizeSlot(SLOT_NAME_NAV_PEV_YEAR, navScope) || h(BIconChevronDoubleLeft, { props: navPrevProps }); var $prevMonthIcon = this.normalizeSlot(SLOT_NAME_NAV_PEV_MONTH, navScope) || h(BIconChevronLeft, { props: navPrevProps }); var $thisMonthIcon = this.normalizeSlot(SLOT_NAME_NAV_THIS_MONTH, navScope) || h(BIconCircleFill, { props: navProps }); var $nextMonthIcon = this.normalizeSlot(SLOT_NAME_NAV_NEXT_MONTH, navScope) || h(BIconChevronLeft, { props: navNextProps }); var $nextYearIcon = this.normalizeSlot(SLOT_NAME_NAV_NEXT_YEAR, navScope) || h(BIconChevronDoubleLeft, { props: navNextProps }); var $nextDecadeIcon = this.normalizeSlot(SLOT_NAME_NAV_NEXT_DECADE, navScope) || h(BIconChevronBarLeft, { props: navNextProps }); // Utility to create the date navigation buttons var makeNavBtn = function makeNavBtn(content, label, handler, btnDisabled, shortcut) { return h('button', { staticClass: 'btn btn-sm border-0 flex-fill', class: [_this6.computedNavButtonVariant, { disabled: btnDisabled }], attrs: { title: label || null, type: 'button', tabindex: noKeyNav ? '-1' : null, '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', attrs: { id: navId, role: 'group', tabindex: noKeyNav ? '-1' : null, 'aria-hidden': disabled ? 'true' : null, 'aria-label': this.labelNav || null, 'aria-controls': gridId } }, [hideDecadeNav ? h() : makeNavBtn($prevDecadeIcon, this.labelPrevDecade, this.gotoPrevDecade, this.prevDecadeDisabled, 'Ctrl+Alt+PageDown'), 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'), hideDecadeNav ? h() : makeNavBtn($nextDecadeIcon, this.labelNextDecade, this.gotoNextDecade, this.nextDecadeDisabled, 'Ctrl+Alt+PageUp')]); // Caption for calendar grid var $gridCaption = h('header', { staticClass: 'b-calendar-grid-caption text-center font-weight-bold', class: { 'text-muted': disabled }, attrs: { id: gridCaptionId, 'aria-live': isLive ? 'polite' : null, 'aria-atomic': isLive ? 'true' : null }, key: 'grid-caption' }, this.formatYearMonth(this.calendarFirstDay)); // Calendar weekday headings var $gridWeekDays = h('div', { staticClass: 'b-calendar-grid-weekdays row no-gutters border-bottom', attrs: { 'aria-hidden': 'true' } }, this.calendarHeadings.map(function (d, idx) { return h('small', { staticClass: 'col text-truncate', class: { 'text-muted': disabled }, attrs: { title: d.label === d.text ? null : d.label, 'aria-label': d.label }, key: idx }, 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 && _this6.gridHasFocus, // Styling disabled: day.isDisabled || disabled, active: isSelected }, _defineProperty(_class, _this6.computedVariant, isSelected), _defineProperty(_class, _this6.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 _this6.onClickDay(day); } } }, day.day); return h('div', // Cell with button { 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 || disabled ? 'true' : null, 'aria-label': [day.label, isSelected ? "(".concat(_this6.labelSelected, ")") : null, isToday ? "(".concat(_this6.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 }, key: dIndex }, [$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', { staticClass: 'row no-gutters', key: week[0].ymd }, $cells); }); $gridBody = h('div', { // A key is only required on the body if we add in transition support staticClass: 'b-calendar-grid-body', style: disabled ? { pointerEvents: 'none' } : {} // key: this.activeYMD.slice(0, -3) }, $gridBody); var $gridHelp = h('footer', { staticClass: 'b-calendar-grid-help border-top small text-muted text-center bg-light', attrs: { id: gridHelpId } }, [h('div', { staticClass: 'small' }, this.labelHelp)]); var $grid = h('div', { staticClass: 'b-calendar-grid form-control h-auto text-center', attrs: { id: gridId, role: 'application', tabindex: noKeyNav ? '-1' : disabled ? null : '0', 'data-month': activeYMD.slice(0, -3), // `YYYY-MM`, mainly for testing 'aria-roledescription': this.labelCalendar || null, 'aria-labelledby': gridCaptionId, 'aria-describedby': gridHelpId, // `aria-readonly` is not considered valid on `role="application"` // https://www.w3.org/TR/wai-aria-1.1/#aria-readonly // 'aria-readonly': this.readonly && !disabled ? 'true' : null, 'aria-disabled': disabled ? 'true' : null, 'aria-activedescendant': activeId }, on: { keydown: this.onKeydownGrid, focus: this.setGridFocusFlag, blur: this.setGridFocusFlag }, ref: 'grid' }, [$gridCaption, $gridWeekDays, $gridBody, $gridHelp]); // Optional bottom slot var $slot = this.normalizeSlot(); $slot = $slot ? h('footer', { staticClass: 'b-calendar-footer' }, $slot) : h(); var $widget = h('div', { staticClass: 'b-calendar-inner', style: this.block ? {} : { width: this.width }, attrs: { id: widgetId, dir: isRTL ? 'rtl' : 'ltr', lang: this.computedLocale || null, role: 'group', 'aria-disabled': 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.bvAttrs['aria-describedby'], valueId, gridHelpId].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', class: { 'd-block': this.block } }, [$widget]); } }); var CalendarPlugin = /*#__PURE__*/pluginFactory({ components: { BCalendar: BCalendar } }); var props$i = makePropsConfigurable({ bgVariant: makeProp(PROP_TYPE_STRING), borderVariant: makeProp(PROP_TYPE_STRING), tag: makeProp(PROP_TYPE_STRING, 'div'), textVariant: makeProp(PROP_TYPE_STRING) }, NAME_CARD); // --- Mixin --- // @vue/component var cardMixin = Vue__default['default'].extend({ props: props$i }); var props$j = makePropsConfigurable({ title: makeProp(PROP_TYPE_STRING), titleTag: makeProp(PROP_TYPE_STRING, 'h4') }, NAME_CARD_TITLE); // --- Main component --- // @vue/component var BCardTitle = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_TITLE, functional: true, props: props$j, 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 || toString$1(props.title)); } }); var props$k = makePropsConfigurable({ subTitle: makeProp(PROP_TYPE_STRING), subTitleTag: makeProp(PROP_TYPE_STRING, 'h6'), subTitleTextVariant: makeProp(PROP_TYPE_STRING, 'muted') }, NAME_CARD_SUB_TITLE); // --- Main component --- // @vue/component var BCardSubTitle = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_SUB_TITLE, functional: true, props: props$k, 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 || toString$1(props.subTitle)); } }); var props$l = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$j), props$k), copyProps(props$i, prefixPropName.bind(null, 'body'))), {}, { bodyClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), overlay: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_CARD_BODY); // --- Main component --- // @vue/component var BCardBody = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_BODY, functional: true, props: props$l, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, children = _ref.children; var bodyBgVariant = props.bodyBgVariant, bodyBorderVariant = props.bodyBorderVariant, bodyTextVariant = props.bodyTextVariant; var $title = h(); if (props.title) { $title = h(BCardTitle, { props: pluckProps(props$j, props) }); } var $subTitle = h(); if (props.subTitle) { $subTitle = h(BCardSubTitle, { props: pluckProps(props$k, props), class: ['mb-2'] }); } return h(props.bodyTag, a(data, { staticClass: 'card-body', class: [(_ref2 = { 'card-img-overlay': props.overlay }, _defineProperty(_ref2, "bg-".concat(bodyBgVariant), bodyBgVariant), _defineProperty(_ref2, "border-".concat(bodyBorderVariant), bodyBorderVariant), _defineProperty(_ref2, "text-".concat(bodyTextVariant), bodyTextVariant), _ref2), props.bodyClass] }), [$title, $subTitle, children]); } }); var props$m = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, copyProps(props$i, prefixPropName.bind(null, 'header'))), {}, { header: makeProp(PROP_TYPE_STRING), headerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), headerHtml: makeProp(PROP_TYPE_STRING) })), NAME_CARD_HEADER); // --- Main component --- // @vue/component var BCardHeader = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_HEADER, functional: true, props: props$m, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, children = _ref.children; var headerBgVariant = props.headerBgVariant, headerBorderVariant = props.headerBorderVariant, headerTextVariant = props.headerTextVariant; return h(props.headerTag, a(data, { staticClass: 'card-header', class: [props.headerClass, (_ref2 = {}, _defineProperty(_ref2, "bg-".concat(headerBgVariant), headerBgVariant), _defineProperty(_ref2, "border-".concat(headerBorderVariant), headerBorderVariant), _defineProperty(_ref2, "text-".concat(headerTextVariant), headerTextVariant), _ref2)], domProps: children ? {} : htmlOrText(props.headerHtml, props.header) }), children); } }); var props$n = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, copyProps(props$i, prefixPropName.bind(null, 'footer'))), {}, { footer: makeProp(PROP_TYPE_STRING), footerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), footerHtml: makeProp(PROP_TYPE_STRING) })), NAME_CARD_FOOTER); // --- Main component --- // @vue/component var BCardFooter = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_FOOTER, functional: true, props: props$n, render: function render(h, _ref) { var _ref2; var props = _ref.props, data = _ref.data, children = _ref.children; var footerBgVariant = props.footerBgVariant, footerBorderVariant = props.footerBorderVariant, footerTextVariant = props.footerTextVariant; return h(props.footerTag, a(data, { staticClass: 'card-footer', class: [props.footerClass, (_ref2 = {}, _defineProperty(_ref2, "bg-".concat(footerBgVariant), footerBgVariant), _defineProperty(_ref2, "border-".concat(footerBorderVariant), footerBorderVariant), _defineProperty(_ref2, "text-".concat(footerTextVariant), footerTextVariant), _ref2)], domProps: children ? {} : htmlOrText(props.footerHtml, props.footer) }), children); } }); // 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>'; // --- 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); }; // --- Props --- var props$o = makePropsConfigurable({ alt: makeProp(PROP_TYPE_STRING), blank: makeProp(PROP_TYPE_BOOLEAN, false), blankColor: makeProp(PROP_TYPE_STRING, 'transparent'), block: makeProp(PROP_TYPE_BOOLEAN, false), center: makeProp(PROP_TYPE_BOOLEAN, false), fluid: makeProp(PROP_TYPE_BOOLEAN, false), // Gives fluid images class `w-100` to make them grow to fit container fluidGrow: makeProp(PROP_TYPE_BOOLEAN, false), height: makeProp(PROP_TYPE_NUMBER_STRING), left: makeProp(PROP_TYPE_BOOLEAN, false), right: makeProp(PROP_TYPE_BOOLEAN, false), // Possible values: // `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 rounded: makeProp(PROP_TYPE_BOOLEAN_STRING, false), sizes: makeProp(PROP_TYPE_ARRAY_STRING), src: makeProp(PROP_TYPE_STRING), srcset: makeProp(PROP_TYPE_ARRAY_STRING), thumbnail: makeProp(PROP_TYPE_BOOLEAN, false), width: makeProp(PROP_TYPE_NUMBER_STRING) }, NAME_IMG); // --- Main component --- // @vue/component var BImg = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_IMG, functional: true, props: props$o, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data; var alt = props.alt, src = props.src, block = props.block, fluidGrow = props.fluidGrow, rounded = props.rounded; var width = toInteger(props.width) || null; var height = toInteger(props.height) || null; var align = null; 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: 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 || fluidGrow, 'w-100': fluidGrow, rounded: rounded === '' || rounded === true }, _defineProperty(_class, "rounded-".concat(rounded), isString(rounded) && rounded !== ''), _defineProperty(_class, align, align), _defineProperty(_class, 'd-block', block), _class) })); } }); var props$p = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, pick(props$o, ['src', 'alt', 'width', 'height', 'left', 'right'])), {}, { bottom: makeProp(PROP_TYPE_BOOLEAN, false), end: makeProp(PROP_TYPE_BOOLEAN, false), start: makeProp(PROP_TYPE_BOOLEAN, false), top: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_CARD_IMG); // --- Main component --- // @vue/component var BCardImg = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_IMG, functional: true, props: props$p, render: function render(h, _ref) { var props = _ref.props, data = _ref.data; var src = props.src, alt = props.alt, width = props.width, height = props.height; 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: src, alt: alt, width: width, height: height } })); } }); var cardImgProps = copyProps(props$p, prefixPropName.bind(null, 'img')); cardImgProps.imgSrc.required = false; var props$q = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$l), props$m), props$n), cardImgProps), props$i), {}, { align: makeProp(PROP_TYPE_STRING), noBody: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_CARD); // --- Main component --- // @vue/component var BCard = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD, functional: true, props: props$q, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, slots = _ref.slots, scopedSlots = _ref.scopedSlots; var imgSrc = props.imgSrc, imgLeft = props.imgLeft, imgRight = props.imgRight, imgStart = props.imgStart, imgEnd = props.imgEnd, imgBottom = props.imgBottom, header = props.header, headerHtml = props.headerHtml, footer = props.footer, footerHtml = props.footerHtml, align = props.align, textVariant = props.textVariant, bgVariant = props.bgVariant, borderVariant = props.borderVariant; var $scopedSlots = scopedSlots || {}; var $slots = slots(); var slotScope = {}; var $imgFirst = h(); var $imgLast = h(); if (imgSrc) { var $img = h(BCardImg, { props: pluckProps(cardImgProps, props, unprefixPropName.bind(null, 'img')) }); if (imgBottom) { $imgLast = $img; } else { $imgFirst = $img; } } var $header = h(); var hasHeaderSlot = hasNormalizedSlot(SLOT_NAME_HEADER, $scopedSlots, $slots); if (hasHeaderSlot || header || headerHtml) { $header = h(BCardHeader, { props: pluckProps(props$m, props), domProps: hasHeaderSlot ? {} : htmlOrText(headerHtml, header) }, normalizeSlot(SLOT_NAME_HEADER, slotScope, $scopedSlots, $slots)); } var $content = normalizeSlot(SLOT_NAME_DEFAULT, slotScope, $scopedSlots, $slots); // Wrap content in `<card-body>` when `noBody` prop set if (!props.noBody) { $content = h(BCardBody, { props: pluckProps(props$l, props) }, $content); // When the `overlap` prop is set we need to wrap the `<b-card-img>` and `<b-card-body>` // into a relative positioned wrapper to don't distract a potential header or footer if (props.overlay && imgSrc) { $content = h('div', { staticClass: 'position-relative' }, [$imgFirst, $content, $imgLast]); // Reset image variables since they are already in the wrapper $imgFirst = h(); $imgLast = h(); } } var $footer = h(); var hasFooterSlot = hasNormalizedSlot(SLOT_NAME_FOOTER, $scopedSlots, $slots); if (hasFooterSlot || footer || footerHtml) { $footer = h(BCardFooter, { props: pluckProps(props$n, props), domProps: hasHeaderSlot ? {} : htmlOrText(footerHtml, footer) }, normalizeSlot(SLOT_NAME_FOOTER, slotScope, $scopedSlots, $slots)); } return h(props.tag, a(data, { staticClass: 'card', class: (_class = { 'flex-row': imgLeft || imgStart, 'flex-row-reverse': (imgRight || imgEnd) && !(imgLeft || imgStart) }, _defineProperty(_class, "text-".concat(align), align), _defineProperty(_class, "bg-".concat(bgVariant), bgVariant), _defineProperty(_class, "border-".concat(borderVariant), borderVariant), _defineProperty(_class, "text-".concat(textVariant), textVariant), _class) }), [$imgFirst, $header, $content, $footer, $imgLast]); } }); var OBSERVER_PROP_NAME = '__bv__visibility_observer'; 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); } }); }); } /* istanbul ignore next */ }, { key: "handler", value: function handler(entries) { 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() { /* istanbul ignore next */ this.observer && this.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 (RX_DIGITS.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 _watch$2; var MODEL_PROP_NAME_SHOW = 'show'; var MODEL_EVENT_NAME_SHOW = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_SHOW; // --- Props --- var imgProps = omit(props$o, ['blank']); var props$r = makePropsConfigurable(_objectSpread2(_objectSpread2({}, imgProps), {}, _defineProperty({ blankColor: makeProp(PROP_TYPE_STRING, 'transparent'), blankHeight: makeProp(PROP_TYPE_NUMBER_STRING), // If `null`, a blank image is generated blankSrc: makeProp(PROP_TYPE_STRING, null), blankWidth: makeProp(PROP_TYPE_NUMBER_STRING), // Distance away from viewport (in pixels) // before being considered "visible" offset: makeProp(PROP_TYPE_NUMBER_STRING, 360) }, MODEL_PROP_NAME_SHOW, makeProp(PROP_TYPE_BOOLEAN, false))), NAME_IMG_LAZY); // --- Main component --- // @vue/component var BImgLazy = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_IMG_LAZY, directives: { 'b-visible': VBVisible }, props: props$r, data: function data() { return { isShown: this[MODEL_PROP_NAME_SHOW] }; }, computed: { computedSrc: function computedSrc() { var blankSrc = this.blankSrc; return !blankSrc || this.isShown ? this.src : blankSrc; }, computedBlank: function computedBlank() { return !(this.isShown || this.blankSrc); }, computedWidth: function computedWidth() { var width = this.width; return this.isShown ? width : this.blankWidth || width; }, computedHeight: function computedHeight() { var height = this.height; return this.isShown ? height : this.blankHeight || 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: (_watch$2 = {}, _defineProperty(_watch$2, MODEL_PROP_NAME_SHOW, function (newValue, oldValue) { if (newValue !== oldValue) { // If `IntersectionObserver` support is not available, image is always shown var visible = HAS_INTERACTION_OBSERVER_SUPPORT ? newValue : true; this.isShown = visible; // Ensure the show prop is synced (when no `IntersectionObserver`) if (visible !== newValue) { this.$nextTick(this.updateShowProp); } } }), _defineProperty(_watch$2, "isShown", function isShown(newValue, oldValue) { // Update synched show prop if (newValue !== oldValue) { this.updateShowProp(); } }), _watch$2), mounted: function mounted() { // If `IntersectionObserver` is not available, image is always shown this.isShown = HAS_INTERACTION_OBSERVER_SUPPORT ? this[MODEL_PROP_NAME_SHOW] : true; }, methods: { updateShowProp: function updateShowProp() { this.$emit(MODEL_EVENT_NAME_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: _objectSpread2({ // Computed value props src: this.computedSrc, blank: this.computedBlank, width: this.computedWidth, height: this.computedHeight, srcset: this.computedSrcset || null, sizes: this.computedSizes || null }, pluckProps(imgProps, this.$props)) }); } }); var props$s = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, omit(props$r, keys(props$o))), omit(props$p, ['src', 'alt', 'width', 'height']))), NAME_CARD_IMG_LAZY); // --- Main component --- // @vue/component var BCardImgLazy = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_IMG_LAZY, functional: true, props: props$s, 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(BImgLazy, a(data, { class: [baseClass], // Exclude `left` and `right` props before passing to `<b-img-lazy>` props: omit(props, ['left', 'right']) })); } }); var props$t = makePropsConfigurable({ textTag: makeProp(PROP_TYPE_STRING, 'p') }, NAME_CARD_TEXT); // --- Main component --- // @vue/component var BCardText = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_TEXT, functional: true, props: props$t, 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$u = makePropsConfigurable({ columns: makeProp(PROP_TYPE_BOOLEAN, false), deck: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_CARD_GROUP); // --- Main component --- // @vue/component var BCardGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CARD_GROUP, 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, { 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 https://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 truly 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 _watch$3; var _makeModelMixin$2 = makeModelMixin('value', { type: PROP_TYPE_NUMBER, defaultValue: 0 }), modelMixin$2 = _makeModelMixin$2.mixin, modelProps$2 = _makeModelMixin$2.props, MODEL_PROP_NAME$2 = _makeModelMixin$2.prop, MODEL_EVENT_NAME$2 = _makeModelMixin$2.event; // 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' }; // --- Helper methods --- // 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; }; // --- Props --- var props$v = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$2), {}, { background: makeProp(PROP_TYPE_STRING), controls: makeProp(PROP_TYPE_BOOLEAN, false), // Enable cross-fade animation instead of slide animation fade: makeProp(PROP_TYPE_BOOLEAN, false), // Sniffed by carousel-slide imgHeight: makeProp(PROP_TYPE_NUMBER_STRING), // Sniffed by carousel-slide imgWidth: makeProp(PROP_TYPE_NUMBER_STRING), indicators: makeProp(PROP_TYPE_BOOLEAN, false), interval: makeProp(PROP_TYPE_NUMBER, 5000), labelGotoSlide: makeProp(PROP_TYPE_STRING, 'Goto slide'), labelIndicators: makeProp(PROP_TYPE_STRING, 'Select a slide to display'), labelNext: makeProp(PROP_TYPE_STRING, 'Next slide'), labelPrev: makeProp(PROP_TYPE_STRING, 'Previous slide'), // Disable slide/fade animation noAnimation: makeProp(PROP_TYPE_BOOLEAN, false), // Disable pause on hover noHoverPause: makeProp(PROP_TYPE_BOOLEAN, false), // Sniffed by carousel-slide noTouch: makeProp(PROP_TYPE_BOOLEAN, false), // Disable wrapping/looping when start/end is reached noWrap: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_CAROUSEL); // --- Main component --- // @vue/component var BCarousel = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CAROUSEL, mixins: [idMixin, modelMixin$2, normalizeSlotMixin], provide: function provide() { return { bvCarousel: this }; }, props: props$v, data: function data() { return { index: this[MODEL_PROP_NAME$2] || 0, isSliding: false, transitionEndEvent: null, slides: [], direction: null, isPaused: !(toInteger(this.interval, 0) > 0), // Touch event handling values touchStartX: 0, touchDeltaX: 0 }; }, computed: { numSlides: function numSlides() { return this.slides.length; } }, watch: (_watch$3 = {}, _defineProperty(_watch$3, MODEL_PROP_NAME$2, function (newValue, oldValue) { if (newValue !== oldValue) { this.setSlide(toInteger(newValue, 0)); } }), _defineProperty(_watch$3, "interval", function interval(newValue, oldValue) { /* istanbul ignore next */ if (newValue === oldValue) { return; } if (!newValue) { // Pausing slide show this.pause(false); } else { // Restarting or Changing interval this.pause(true); this.start(false); } }), _defineProperty(_watch$3, "isPaused", function isPaused(newValue, oldValue) { if (newValue !== oldValue) { this.$emit(newValue ? EVENT_NAME_PAUSED : EVENT_NAME_UNPAUSED); } }), _defineProperty(_watch$3, "index", function index(to, from) { /* istanbul ignore next */ if (to === from || this.isSliding) { return; } this.doSlide(to, from); }), _watch$3), created: function created() { // Create private non-reactive props this.$_interval = null; this.$_animationTimeout = null; this.$_touchTimeout = null; this.$_observer = null; // Set initial paused state this.isPaused = !(toInteger(this.interval, 0) > 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 this.setObserver(true); }, beforeDestroy: function beforeDestroy() { this.clearInterval(); this.clearAnimationTimeout(); this.clearTouchTimeout(); this.setObserver(false); }, methods: { clearInterval: function (_clearInterval) { function clearInterval() { return _clearInterval.apply(this, arguments); } clearInterval.toString = function () { return _clearInterval.toString(); }; return clearInterval; }(function () { clearInterval(this.$_interval); this.$_interval = null; }), clearAnimationTimeout: function clearAnimationTimeout() { clearTimeout(this.$_animationTimeout); this.$_animationTimeout = null; }, clearTouchTimeout: function clearTouchTimeout() { clearTimeout(this.$_touchTimeout); this.$_touchTimeout = null; }, setObserver: function setObserver() { var on = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; this.$_observer && this.$_observer.disconnect(); this.$_observer = null; if (on) { this.$_observer = observeDom(this.$refs.inner, this.updateSlides.bind(this), { subtree: false, childList: true, attributes: true, attributeFilter: ['id'] }); } }, // 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 (IS_BROWSER && document.visibilityState && document.hidden) { return; } var noWrap = this.noWrap; var numSlides = this.numSlides; // Make sure we have an integer (you never know!) slide = mathFloor(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(EVENT_NAME_SLIDING_END, function () { // Wrap in `requestAF()` to allow the slide to properly finish to avoid glitching requestAF(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[MODEL_PROP_NAME$2]) { this.$emit(MODEL_EVENT_NAME$2, 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(event) { if (!event) { this.isPaused = true; } this.clearInterval(); }, // Start auto rotate slides start: function start(event) { if (!event) { this.isPaused = false; } /* istanbul ignore next: most likely will never happen, but just in case */ this.clearInterval(); // Don't start if no interval, or less than 2 slides if (this.interval && this.numSlides > 1) { this.$_interval = setInterval(this.next, mathMax(1000, this.interval)); } }, // Restart auto rotate slides when focus/hover leaves the carousel /* istanbul ignore next */ restart: function restart() { if (!this.$el.contains(getActiveElement())) { 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(EVENT_NAME_SLIDING_START, to); // Update v-model this.$emit(MODEL_EVENT_NAME$2, 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(EVENT_NAME_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 (event) { return eventOff(nextSlide, event, onceTransEnd, EVENT_OPTIONS_NO_CAPTURE); }); } _this2.clearAnimationTimeout(); 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(EVENT_NAME_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(nextSlide, 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 = mathMax(0, mathMin(mathFloor(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(event, fn) { var keyCode = event.keyCode; if (event.type === 'click' || keyCode === CODE_SPACE || keyCode === CODE_ENTER) { stopEvent(event); fn(); } }, /* istanbul ignore next: JSDOM doesn't support touch events */ handleSwipe: function handleSwipe() { var absDeltaX = mathAbs(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(); } }, /* istanbul ignore next: JSDOM doesn't support touch events */ touchStart: function touchStart(event) { if (HAS_POINTER_EVENT_SUPPORT && PointerType[event.pointerType.toUpperCase()]) { this.touchStartX = event.clientX; } else if (!HAS_POINTER_EVENT_SUPPORT) { this.touchStartX = event.touches[0].clientX; } }, /* istanbul ignore next: JSDOM doesn't support touch events */ touchMove: function touchMove(event) { // Ensure swiping with one touch and not pinching if (event.touches && event.touches.length > 1) { this.touchDeltaX = 0; } else { this.touchDeltaX = event.touches[0].clientX - this.touchStartX; } }, /* istanbul ignore next: JSDOM doesn't support touch events */ touchEnd: function touchEnd(event) { if (HAS_POINTER_EVENT_SUPPORT && PointerType[event.pointerType.toUpperCase()]) { this.touchDeltaX = event.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); this.clearTouchTimeout(); this.$_touchTimeout = setTimeout(this.start, TOUCH_EVENT_COMPAT_WAIT + mathMax(1000, this.interval)); } }, render: function render(h) { var _this3 = this; var indicators = this.indicators, background = this.background, noAnimation = this.noAnimation, noHoverPause = this.noHoverPause, noTouch = this.noTouch, index = this.index, isSliding = this.isSliding, pause = this.pause, restart = this.restart, touchStart = this.touchStart, touchEnd = this.touchEnd; var idInner = this.safeId('__BV_inner_'); // Wrapper for slides var $inner = h('div', { staticClass: 'carousel-inner', attrs: { id: idInner, role: 'list' }, ref: 'inner' }, [this.normalizeSlot()]); // Prev and next controls var $controls = h(); if (this.controls) { var makeControl = function makeControl(direction, label, handler) { var handlerWrapper = function handlerWrapper(event) { /* istanbul ignore next */ if (!isSliding) { _this3.handleClick(event, handler); } else { stopEvent(event, { propagation: false }); } }; return h('a', { staticClass: "carousel-control-".concat(direction), attrs: { href: '#', role: 'button', 'aria-controls': idInner, 'aria-disabled': isSliding ? 'true' : null }, on: { click: handlerWrapper, keydown: handlerWrapper } }, [h('span', { staticClass: "carousel-control-".concat(direction, "-icon"), attrs: { 'aria-hidden': 'true' } }), h('span', { class: 'sr-only' }, [label])]); }; $controls = [makeControl('prev', this.labelPrev, this.prev), makeControl('next', this.labelNext, this.next)]; } // Indicators var $indicators = h('ol', { staticClass: 'carousel-indicators', directives: [{ name: 'show', value: indicators }], attrs: { id: this.safeId('__BV_indicators_'), 'aria-hidden': indicators ? 'false' : 'true', 'aria-label': this.labelIndicators, 'aria-owns': idInner } }, this.slides.map(function (slide, i) { var handler = function handler(event) { _this3.handleClick(event, function () { _this3.setSlide(i); }); }; return h('li', { class: { active: i === index }, attrs: { role: 'button', id: _this3.safeId("__BV_indicator_".concat(i + 1, "_")), tabindex: indicators ? '0' : '-1', 'aria-current': i === index ? 'true' : 'false', 'aria-label': "".concat(_this3.labelGotoSlide, " ").concat(i + 1), 'aria-describedby': slide.id || null, 'aria-controls': idInner }, on: { click: handler, keydown: handler }, key: "slide_".concat(i) }); })); var on = { mouseenter: noHoverPause ? noop : pause, mouseleave: noHoverPause ? noop : restart, focusin: pause, focusout: restart, keydown: function keydown(event) { /* istanbul ignore next */ if (/input|textarea/i.test(event.target.tagName)) { return; } var keyCode = event.keyCode; if (keyCode === CODE_LEFT || keyCode === CODE_RIGHT) { stopEvent(event); _this3[keyCode === CODE_LEFT ? 'prev' : 'next'](); } } }; // Touch support event handlers for environment if (HAS_TOUCH_SUPPORT && !noTouch) { // Attach appropriate listeners (prepend event name with '&' for passive mode) /* istanbul ignore next: JSDOM doesn't support touch events */ if (HAS_POINTER_EVENT_SUPPORT) { on['&pointerdown'] = touchStart; on['&pointerup'] = touchEnd; } else { on['&touchstart'] = touchStart; on['&touchmove'] = this.touchMove; on['&touchend'] = touchEnd; } } // Return the carousel return h('div', { staticClass: 'carousel', class: { slide: !noAnimation, 'carousel-fade': !noAnimation && this.fade, 'pointer-event': HAS_TOUCH_SUPPORT && HAS_POINTER_EVENT_SUPPORT && !noTouch }, style: { background: background }, attrs: { role: 'region', id: this.safeId(), 'aria-busy': isSliding ? 'true' : 'false' }, on: on }, [$inner, $controls, $indicators]); } }); var imgProps$1 = { imgAlt: makeProp(PROP_TYPE_STRING), imgBlank: makeProp(PROP_TYPE_BOOLEAN, false), imgBlankColor: makeProp(PROP_TYPE_STRING, 'transparent'), imgHeight: makeProp(PROP_TYPE_NUMBER_STRING), imgSrc: makeProp(PROP_TYPE_STRING), imgWidth: makeProp(PROP_TYPE_NUMBER_STRING) }; var props$w = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), imgProps$1), {}, { background: makeProp(PROP_TYPE_STRING), caption: makeProp(PROP_TYPE_STRING), captionHtml: makeProp(PROP_TYPE_STRING), captionTag: makeProp(PROP_TYPE_STRING, 'h3'), contentTag: makeProp(PROP_TYPE_STRING, 'div'), contentVisibleUp: makeProp(PROP_TYPE_STRING), text: makeProp(PROP_TYPE_STRING), textHtml: makeProp(PROP_TYPE_STRING), textTag: makeProp(PROP_TYPE_STRING, 'p') })), NAME_CAROUSEL_SLIDE); // --- Main component --- // @vue/component var BCarouselSlide = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CAROUSEL_SLIDE, mixins: [idMixin, normalizeSlotMixin], inject: { bvCarousel: { // Explicitly disable touch if not a child of carousel default: function _default() { return { noTouch: true }; } } }, props: props$w, 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 $img = this.normalizeSlot(SLOT_NAME_IMG); if (!$img && (this.imgSrc || this.imgBlank)) { var on = {}; // Touch support event handler /* istanbul ignore if: difficult to test in JSDOM */ if (!this.bvCarousel.noTouch && HAS_TOUCH_SUPPORT) { on.dragstart = function (event) { return stopEvent(event, { propagation: false }); }; } $img = h(BImg, { props: _objectSpread2(_objectSpread2({}, pluckProps(imgProps$1, this.$props, unprefixPropName.bind(null, 'img'))), {}, { width: this.computedWidth, height: this.computedHeight, fluidGrow: true, block: true }), on: on }); } var $contentChildren = [// Caption this.caption || this.captionHtml ? h(this.captionTag, { domProps: htmlOrText(this.captionHtml, this.caption) }) : false, // Text this.text || this.textHtml ? h(this.textTag, { domProps: htmlOrText(this.textHtml, this.text) }) : false, // Children this.normalizeSlot() || false]; var $content = h(); if ($contentChildren.some(identity)) { $content = h(this.contentTag, { staticClass: 'carousel-caption', class: this.contentClasses }, $contentChildren.map(function ($child) { return $child || 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 } }); var CLASS_NAME_SHOW = 'show'; // Generic collapse transion helper component // Transition event handler helpers var onEnter = function onEnter(el) { setStyle(el, 'height', 0); // In a `requestAF()` for `appear` to work requestAF(function () { reflow(el); setStyle(el, 'height', "".concat(el.scrollHeight, "px")); }); }; var onAfterEnter = function onAfterEnter(el) { removeStyle(el, 'height'); }; var onLeave = function onLeave(el) { setStyle(el, 'height', 'auto'); setStyle(el, 'display', 'block'); setStyle(el, 'height', "".concat(getBCR(el).height, "px")); reflow(el); setStyle(el, 'height', 0); }; var onAfterLeave = function onAfterLeave(el) { removeStyle(el, 'height'); }; // --- Constants --- // 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 }; // --- Main component --- var props$x = { // // If `true` (and `visible` is `true` on mount), animate initially visible appear: makeProp(PROP_TYPE_BOOLEAN, false) }; // --- Main component --- // @vue/component var BVCollapse = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_COLLAPSE_HELPER, functional: true, props: props$x, 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: `<transition>` supports a single root element only children); } }); var _watch$4; var ROOT_ACTION_EVENT_NAME_TOGGLE = getRootActionEventName(NAME_COLLAPSE, 'toggle'); var ROOT_ACTION_EVENT_NAME_REQUEST_STATE = getRootActionEventName(NAME_COLLAPSE, 'request-state'); var ROOT_EVENT_NAME_ACCORDION = getRootEventName(NAME_COLLAPSE, 'accordion'); var ROOT_EVENT_NAME_STATE = getRootEventName(NAME_COLLAPSE, 'state'); var ROOT_EVENT_NAME_SYNC_STATE = getRootEventName(NAME_COLLAPSE, 'sync-state'); var _makeModelMixin$3 = makeModelMixin('visible', { type: PROP_TYPE_BOOLEAN, defaultValue: false }), modelMixin$3 = _makeModelMixin$3.mixin, modelProps$3 = _makeModelMixin$3.props, MODEL_PROP_NAME$3 = _makeModelMixin$3.prop, MODEL_EVENT_NAME$3 = _makeModelMixin$3.event; // --- Props --- var props$y = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$3), {}, { // If `true` (and `visible` is `true` on mount), animate initially visible accordion: makeProp(PROP_TYPE_STRING), appear: makeProp(PROP_TYPE_BOOLEAN, false), isNav: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div') })), NAME_COLLAPSE); // --- Main component --- // @vue/component var BCollapse = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_COLLAPSE, mixins: [idMixin, modelMixin$3, normalizeSlotMixin, listenOnRootMixin], props: props$y, data: function data() { return { show: this[MODEL_PROP_NAME$3], transitioning: false }; }, computed: { classObject: function classObject() { var transitioning = this.transitioning; return { 'navbar-collapse': this.isNav, collapse: !transitioning, show: this.show && !transitioning }; }, slotScope: function slotScope() { var _this = this; return { visible: this.show, close: function close() { _this.show = false; } }; } }, watch: (_watch$4 = {}, _defineProperty(_watch$4, MODEL_PROP_NAME$3, function (newValue) { if (newValue !== this.show) { this.show = newValue; } }), _defineProperty(_watch$4, "show", function show(newValue, oldValue) { if (newValue !== oldValue) { this.emitState(); } }), _watch$4), created: function created() { this.show = this[MODEL_PROP_NAME$3]; }, mounted: function mounted() { var _this2 = this; this.show = this[MODEL_PROP_NAME$3]; // Listen for toggle events to open/close us this.listenOnRoot(ROOT_ACTION_EVENT_NAME_TOGGLE, this.handleToggleEvt); // Listen to other collapses for accordion events this.listenOnRoot(ROOT_EVENT_NAME_ACCORDION, this.handleAccordionEvt); if (this.isNav) { // Set up handlers this.setWindowEvents(true); this.handleResize(); } this.$nextTick(function () { _this2.emitState(); }); // Listen for "Sync state" requests from `v-b-toggle` this.listenOnRoot(ROOT_ACTION_EVENT_NAME_REQUEST_STATE, function (id) { if (id === _this2.safeId()) { _this2.$nextTick(_this2.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(); }, /* istanbul ignore next */ deactivated: function deactivated() { if (this.isNav) { this.setWindowEvents(false); } }, /* istanbul ignore next */ activated: function activated() { if (this.isNav) { this.setWindowEvents(true); } this.emitSync(); }, beforeDestroy: function beforeDestroy() { // Trigger state emit if needed this.show = false; if (this.isNav && IS_BROWSER) { 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(EVENT_NAME_SHOW); }, onAfterEnter: function onAfterEnter() { this.transitioning = false; this.$emit(EVENT_NAME_SHOWN); }, onLeave: function onLeave() { this.transitioning = true; // This should be moved out so we can add cancellable events this.$emit(EVENT_NAME_HIDE); }, onAfterLeave: function onAfterLeave() { this.transitioning = false; this.$emit(EVENT_NAME_HIDDEN); }, emitState: function emitState() { var show = this.show, accordion = this.accordion; var id = this.safeId(); this.$emit(MODEL_EVENT_NAME$3, show); // Let `v-b-toggle` know the state of this collapse this.emitOnRoot(ROOT_EVENT_NAME_STATE, id, show); if (accordion && show) { // Tell the other collapses in this accordion to close this.emitOnRoot(ROOT_EVENT_NAME_ACCORDION, id, 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.emitOnRoot(ROOT_EVENT_NAME_SYNC_STATE, 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 $el = this.$el; var restore = hasClass($el, CLASS_NAME_SHOW); removeClass($el, CLASS_NAME_SHOW); var isBlock = getCS($el).display === 'block'; if (restore) { addClass($el, CLASS_NAME_SHOW); } return isBlock; }, clickHandler: function clickHandler(event) { var el = event.target; // If we are in a nav/navbar, close the collapse when non-disabled link clicked /* istanbul ignore next: can't test `getComputedStyle()` in JSDOM */ if (!this.isNav || !el || getCS(this.$el).display !== 'block') { return; } // Only close the collapse if it is not forced to be `display: block !important` if ((matches(el, '.nav-link,.dropdown-item') || closest('.nav-link,.dropdown-item', el)) && !this.checkDisplayBlock()) { this.show = false; } }, handleToggleEvt: function handleToggleEvt(id) { if (id === this.safeId()) { this.toggle(); } }, handleAccordionEvt: function handleAccordionEvt(openedId, openAccordion) { var accordion = this.accordion, show = this.show; if (!accordion || accordion !== openAccordion) { return; } var isThis = openedId === this.safeId(); // Open this collapse if not shown or // close this collapse if shown if (isThis && !show || !isThis && 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 appear = this.appear; var $content = h(this.tag, { class: this.classObject, directives: [{ name: 'show', value: this.show }], attrs: { id: this.safeId() }, on: { click: this.clickHandler } }, this.normalizeSlot(SLOT_NAME_DEFAULT, this.slotScope)); return h(BVCollapse, { props: { appear: appear }, on: { enter: this.onEnter, afterEnter: this.onAfterEnter, leave: this.onLeave, afterLeave: this.onAfterLeave } }, [$content]); } }); // Classes to apply to trigger element var CLASS_BV_TOGGLE_COLLAPSED = 'collapsed'; var CLASS_BV_TOGGLE_NOT_COLLAPSED = 'not-collapsed'; // Property key for handler storage var BV_BASE = '__BV_toggle'; // Root event listener property (Function) var BV_TOGGLE_ROOT_HANDLER = "".concat(BV_BASE, "_HANDLER__"); // Trigger element click handler property (Function) var BV_TOGGLE_CLICK_HANDLER = "".concat(BV_BASE, "_CLICK__"); // Target visibility state property (Boolean) var BV_TOGGLE_STATE = "".concat(BV_BASE, "_STATE__"); // Target ID list property (Array) var BV_TOGGLE_TARGETS = "".concat(BV_BASE, "_TARGETS__"); // Commonly used strings var STRING_FALSE = 'false'; var STRING_TRUE = 'true'; // Commonly used attribute names var ATTR_ARIA_CONTROLS = 'aria-controls'; var ATTR_ARIA_EXPANDED = 'aria-expanded'; var ATTR_ROLE = 'role'; var ATTR_TABINDEX = 'tabindex'; // Commonly used style properties var STYLE_OVERFLOW_ANCHOR = 'overflow-anchor'; // Emitted control event for collapse (emitted to collapse) var ROOT_ACTION_EVENT_NAME_TOGGLE$1 = getRootActionEventName(NAME_COLLAPSE, 'toggle'); // Listen to event for toggle state update (emitted by collapse) var ROOT_EVENT_NAME_STATE$1 = getRootEventName(NAME_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 ROOT_EVENT_NAME_SYNC_STATE$1 = getRootEventName(NAME_COLLAPSE, 'sync-state'); // Private event we send to collapse to request state update sync event var ROOT_ACTION_EVENT_NAME_REQUEST_STATE$1 = getRootActionEventName(NAME_COLLAPSE, 'request-state'); var KEYDOWN_KEY_CODES = [CODE_ENTER, CODE_SPACE]; // --- Helper methods --- var isNonStandardTag$1 = function isNonStandardTag(el) { return !arrayIncludes(['button', 'a'], el.tagName.toLowerCase()); }; var getTargets = function getTargets(_ref, el) { var modifiers = _ref.modifiers, arg = _ref.arg, value = _ref.value; // Any modifiers are considered target IDs var targets = keys(modifiers || {}); // If value is a string, split out individual targets (if space delimited) value = isString(value) ? value.split(RX_SPACE_SPLIT) : value; // Support target ID as link href (`href="#id"`) if (isTag(el.tagName, 'a')) { var href = getAttr(el, 'href') || ''; if (RX_HASH_ID.test(href)) { targets.push(href.replace(RX_HASH, '')); } } // Add ID from `arg` (if provided), and support value // as a single string ID or an array of string IDs // If `value` is not an array or string, then it gets filtered out concat(arg, value).forEach(function (t) { return isString(t) && targets.push(t); }); // Return only unique and truthy target IDs return targets.filter(function (t, index, arr) { return t && arr.indexOf(t) === index; }); }; var removeClickListener = function removeClickListener(el) { var handler = el[BV_TOGGLE_CLICK_HANDLER]; if (handler) { eventOff(el, 'click', handler, EVENT_OPTIONS_PASSIVE); eventOff(el, 'keydown', handler, EVENT_OPTIONS_PASSIVE); } el[BV_TOGGLE_CLICK_HANDLER] = null; }; var addClickListener = function addClickListener(el, vnode) { removeClickListener(el); if (vnode.context) { var handler = function handler(event) { if (!(event.type === 'keydown' && !arrayIncludes(KEYDOWN_KEY_CODES, event.keyCode)) && !isDisabled(el)) { var targets = el[BV_TOGGLE_TARGETS] || []; targets.forEach(function (target) { vnode.context.$root.$emit(ROOT_ACTION_EVENT_NAME_TOGGLE$1, target); }); } }; el[BV_TOGGLE_CLICK_HANDLER] = handler; eventOn(el, 'click', handler, EVENT_OPTIONS_PASSIVE); if (isNonStandardTag$1(el)) { eventOn(el, 'keydown', handler, EVENT_OPTIONS_PASSIVE); } } }; var removeRootListeners = function removeRootListeners(el, vnode) { if (el[BV_TOGGLE_ROOT_HANDLER] && vnode.context) { vnode.context.$root.$off([ROOT_EVENT_NAME_STATE$1, ROOT_EVENT_NAME_SYNC_STATE$1], el[BV_TOGGLE_ROOT_HANDLER]); } el[BV_TOGGLE_ROOT_HANDLER] = null; }; var addRootListeners = function addRootListeners(el, vnode) { removeRootListeners(el, vnode); if (vnode.context) { var handler = function handler(id, state) { // `state` will be `true` if target is expanded if (arrayIncludes(el[BV_TOGGLE_TARGETS] || [], id)) { // Set/Clear 'collapsed' visibility class state el[BV_TOGGLE_STATE] = state; // Set `aria-expanded` and class state on trigger element setToggleState(el, state); } }; el[BV_TOGGLE_ROOT_HANDLER] = handler; // Listen for toggle state changes (public) and sync (private) vnode.context.$root.$on([ROOT_EVENT_NAME_STATE$1, ROOT_EVENT_NAME_SYNC_STATE$1], handler); } }; var setToggleState = function setToggleState(el, state) { // State refers to the visibility of the collapse/sidebar if (state) { removeClass(el, CLASS_BV_TOGGLE_COLLAPSED); addClass(el, CLASS_BV_TOGGLE_NOT_COLLAPSED); setAttr(el, ATTR_ARIA_EXPANDED, STRING_TRUE); } else { removeClass(el, CLASS_BV_TOGGLE_NOT_COLLAPSED); addClass(el, CLASS_BV_TOGGLE_COLLAPSED); setAttr(el, ATTR_ARIA_EXPANDED, STRING_FALSE); } }; // Reset and remove a property from the provided element var resetProp = function resetProp(el, prop) { el[prop] = null; delete el[prop]; }; // Handle directive updates var handleUpdate = function handleUpdate(el, binding, vnode) { /* istanbul ignore next: should never happen */ if (!IS_BROWSER || !vnode.context) { return; } // If element is not a button or link, we add `role="button"` // and `tabindex="0"` for accessibility reasons if (isNonStandardTag$1(el)) { if (!hasAttr(el, ATTR_ROLE)) { setAttr(el, ATTR_ROLE, 'button'); } if (!hasAttr(el, ATTR_TABINDEX)) { setAttr(el, ATTR_TABINDEX, '0'); } } // 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) setToggleState(el, el[BV_TOGGLE_STATE]); // Parse list of target IDs var targets = getTargets(binding, el); // Ensure the `aria-controls` hasn't been overwritten // or removed when vnode updates // Also ensure to set `overflow-anchor` to `none` to prevent // the browser's scroll anchoring behavior /* istanbul ignore else */ if (targets.length > 0) { setAttr(el, ATTR_ARIA_CONTROLS, targets.join(' ')); setStyle(el, STYLE_OVERFLOW_ANCHOR, 'none'); } else { removeAttr(el, ATTR_ARIA_CONTROLS); removeStyle(el, STYLE_OVERFLOW_ANCHOR); } // Add/Update our click listener(s) // Wrap in a `requestAF()` to allow any previous // click handling to occur first requestAF(function () { addClickListener(el, vnode); }); // If targets array has changed, update if (!looseEqual(targets, el[BV_TOGGLE_TARGETS])) { // Update targets array to element storage el[BV_TOGGLE_TARGETS] = targets; // Ensure `aria-controls` is up to date // Request a state update from targets so that we can // ensure expanded state is correct (in most cases) targets.forEach(function (target) { vnode.context.$root.$emit(ROOT_ACTION_EVENT_NAME_REQUEST_STATE$1, target); }); } }; /* * Export our directive */ var VBToggle = { bind: function bind(el, binding, vnode) { // State is initially collapsed until we receive a state event el[BV_TOGGLE_STATE] = false; // Assume no targets initially el[BV_TOGGLE_TARGETS] = []; // Add our root listeners addRootListeners(el, vnode); // Initial update of trigger handleUpdate(el, binding, vnode); }, componentUpdated: handleUpdate, updated: handleUpdate, unbind: function unbind(el, binding, vnode) { removeClickListener(el); // Remove our $root listener removeRootListeners(el, vnode); // Reset custom props resetProp(el, BV_TOGGLE_ROOT_HANDLER); resetProp(el, BV_TOGGLE_CLICK_HANDLER); resetProp(el, BV_TOGGLE_STATE); resetProp(el, BV_TOGGLE_TARGETS); // Reset classes/attrs/styles removeClass(el, CLASS_BV_TOGGLE_COLLAPSED); removeClass(el, CLASS_BV_TOGGLE_NOT_COLLAPSED); removeAttr(el, ATTR_ARIA_EXPANDED); removeAttr(el, ATTR_ARIA_CONTROLS); removeAttr(el, ATTR_ROLE); removeStyle(el, STYLE_OVERFLOW_ANCHOR); } }; var VBTogglePlugin = /*#__PURE__*/pluginFactory({ directives: { VBToggle: VBToggle } }); var CollapsePlugin = /*#__PURE__*/pluginFactory({ components: { BCollapse: BCollapse }, plugins: { VBTogglePlugin: VBTogglePlugin } }); /**! * @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 = 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 && 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 && 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 && !!(window.MSInputMethodContext && document.documentMode); var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); /** * Determines if the browser is Internet Explorer * @method * @memberof Popper.Utils * @param {Number} version to check * @returns {Boolean} isIE */ function isIE(version) { if (version === 11) { return isIE11; } if (version === 10) { return isIE10; } return isIE11 || isIE10; } /** * Returns the offset parent of the given element * @method * @memberof Popper.Utils * @argument {Element} element * @returns {Element} offset parent */ function getOffsetParent(element) { if (!element) { return document.documentElement; } var noOffsetParent = isIE(10) ? document.body : null; // NOTE: 1 DOM access here var offsetParent = element.offsetParent || 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(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(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(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(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()) { 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$1(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$1(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 && /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$1(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$1(+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 PLACEMENT_TOP_START = 'top-start'; var PLACEMENT_TOP_END = 'top-end'; var PLACEMENT_BOTTOM_START = 'bottom-start'; var PLACEMENT_BOTTOM_END = 'bottom-end'; var PLACEMENT_RIGHT_START = 'right-start'; var PLACEMENT_LEFT_START = 'left-start'; 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; }(); var clickOutMixin = Vue__default['default'].extend({ 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() { eventOff(this.clickOutElement, this.clickOutEventName, this._clickOutHandler, EVENT_OPTIONS_NO_CAPTURE); }, methods: { isClickOut: function isClickOut(event) { return !contains(this.$el, event.target); }, _clickOutHandler: function _clickOutHandler(event) { if (this.clickOutHandler && this.isClickOut(event)) { this.clickOutHandler(event); } } } }); var focusInMixin = Vue__default['default'].extend({ 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() { eventOff(this.focusInElement, 'focusin', this._focusInHandler, EVENT_OPTIONS_NO_CAPTURE); }, methods: { _focusInHandler: function _focusInHandler(event) { if (this.focusInHandler) { this.focusInHandler(event); } } } }); var ROOT_EVENT_NAME_SHOWN = getRootEventName(NAME_DROPDOWN, EVENT_NAME_SHOWN); var ROOT_EVENT_NAME_HIDDEN = getRootEventName(NAME_DROPDOWN, EVENT_NAME_HIDDEN); // CSS selectors var SELECTOR_FORM_CHILD = '.dropdown form'; var SELECTOR_ITEM = ['.dropdown-item', '.b-dropdown-form'].map(function (selector) { return "".concat(selector, ":not(.disabled):not([disabled])"); }).join(', '); // --- Helper methods --- // Return an array of visible items var filterVisibles = function filterVisibles(els) { return (els || []).filter(isVisible); }; // --- Props --- var props$z = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$g), {}, { // String: `scrollParent`, `window` or `viewport` // HTMLElement: HTML Element reference boundary: makeProp([HTMLElement, PROP_TYPE_STRING], 'scrollParent'), disabled: makeProp(PROP_TYPE_BOOLEAN, false), // Place left if possible dropleft: makeProp(PROP_TYPE_BOOLEAN, false), // Place right if possible dropright: makeProp(PROP_TYPE_BOOLEAN, false), // Place on top if possible dropup: makeProp(PROP_TYPE_BOOLEAN, false), // Disable auto-flipping of menu from bottom <=> top noFlip: makeProp(PROP_TYPE_BOOLEAN, false), // Number of pixels or a CSS unit value to offset menu // (i.e. `1px`, `1rem`, etc.) offset: makeProp(PROP_TYPE_NUMBER_STRING, 0), popperOpts: makeProp(PROP_TYPE_OBJECT, {}), // Right align menu (default is left align) right: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_DROPDOWN); // --- Mixin --- // @vue/component var dropdownMixin = Vue__default['default'].extend({ mixins: [idMixin, listenOnRootMixin, clickOutMixin, focusInMixin], provide: function provide() { return { bvDropdown: this }; }, inject: { bvNavbar: { default: null } }, props: props$z, 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 ''; }, boundaryClass: function boundaryClass() { // 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 return this.boundary !== 'scrollParent' && !this.inNavbar ? 'position-static' : ''; } }, watch: { visible: function visible(newValue, oldValue) { if (this.visibleChangePrevented) { this.visibleChangePrevented = false; return; } if (newValue !== oldValue) { var eventName = newValue ? EVENT_NAME_SHOW : EVENT_NAME_HIDE; var bvEvent = new BvEvent(eventName, { cancelable: true, vueTarget: this, target: this.$refs.menu, relatedTarget: null, componentId: this.safeId ? this.safeId() : this.id || null }); this.emitEvent(bvEvent); if (bvEvent.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(EVENT_NAME_HIDDEN, this.focusToggler); return; } if (newValue) { 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 private non-reactive props this.$_popper = null; this.$_hideTimeout = null; }, /* istanbul ignore next */ deactivated: function deactivated() { // 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(); this.clearHideTimeout(); }, methods: { // Event emitter emitEvent: function emitEvent(bvEvent) { var type = bvEvent.type; this.emitOnRoot(getRootEventName(NAME_DROPDOWN, type), bvEvent); this.$emit(type, bvEvent); }, 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', NAME_DROPDOWN); } 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.emitOnRoot(ROOT_EVENT_NAME_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(EVENT_NAME_SHOWN); }); }, hideMenu: function hideMenu() { this.whileOpenListen(false); this.emitOnRoot(ROOT_EVENT_NAME_HIDDEN, this); this.$emit(EVENT_NAME_HIDDEN); this.destroyPopper(); }, createPopper: function createPopper(element) { this.destroyPopper(); this.$_popper = new Popper(element, this.$refs.menu, this.getPopperConfig()); }, // Ensure popper event listeners are removed cleanly destroyPopper: function destroyPopper() { this.$_popper && this.$_popper.destroy(); this.$_popper = null; }, // Instructs popper to re-computes the dropdown position // useful if the content changes size updatePopper: function updatePopper() { try { this.$_popper.scheduleUpdate(); } catch (_unused) {} }, clearHideTimeout: function clearHideTimeout() { clearTimeout(this.$_hideTimeout); this.$_hideTimeout = null; }, getPopperConfig: function getPopperConfig() { var placement = PLACEMENT_BOTTOM_START; if (this.dropup) { placement = this.right ? PLACEMENT_TOP_END : PLACEMENT_TOP_START; } else if (this.dropright) { placement = PLACEMENT_RIGHT_START; } else if (this.dropleft) { placement = PLACEMENT_LEFT_START; } else if (this.right) { placement = PLACEMENT_BOTTOM_END; } var popperConfig = { placement: placement, modifiers: { offset: { offset: this.offset || 0 }, flip: { enabled: !this.noFlip } } }; var boundariesElement = this.boundary; if (boundariesElement) { popperConfig.modifiers.preventOverflow = { boundariesElement: boundariesElement }; } return mergeDeep(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_EVENT_NAME_SHOWN, this.rootCloseListener); }, rootCloseListener: function rootCloseListener(vm) { if (vm !== this) { this.visible = false; } }, // Public method to show dropdown show: function show() { var _this2 = this; if (this.disabled) { return; } // Wrap in a `requestAF()` to allow any previous // click handling to occur first requestAF(function () { _this2.visible = true; }); }, // Public method to hide dropdown hide: function hide() { var refocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; /* istanbul ignore next */ if (this.disabled) { return; } this.visible = false; if (refocus) { // Child element is closing the dropdown on click this.$once(EVENT_NAME_HIDDEN, this.focusToggler); } }, // Called only by a button that toggles the menu toggle: function toggle(event) { event = event || {}; // Early exit when not a click event or ENTER, SPACE or DOWN were pressed var _event = event, type = _event.type, keyCode = _event.keyCode; if (type !== 'click' && !(type === 'keydown' && [CODE_ENTER, CODE_SPACE, CODE_DOWN].indexOf(keyCode) !== -1)) { /* istanbul ignore next */ return; } /* istanbul ignore next */ if (this.disabled) { this.visible = false; return; } this.$emit(EVENT_NAME_TOGGLE, event); stopEvent(event); // Toggle visibility if (this.visible) { this.hide(true); } else { this.show(); } }, // Mousedown handler for the toggle /* istanbul ignore next */ onMousedown: function onMousedown(event) { // 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 stopEvent(event, { propagation: false }); }, // Called from dropdown menu context onKeydown: function onKeydown(event) { var keyCode = event.keyCode; if (keyCode === CODE_ESC) { // Close on ESC this.onEsc(event); } else if (keyCode === CODE_DOWN) { // Down Arrow this.focusNext(event, false); } else if (keyCode === CODE_UP) { // Up Arrow this.focusNext(event, true); } }, // If user presses ESC, close the menu onEsc: function onEsc(event) { if (this.visible) { this.visible = false; stopEvent(event); // Return focus to original trigger button this.$once(EVENT_NAME_HIDDEN, this.focusToggler); } }, // Called only in split button mode, for the split button onSplitClick: function onSplitClick(event) { /* istanbul ignore next */ if (this.disabled) { this.visible = false; return; } this.$emit(EVENT_NAME_CLICK, event); }, // Shared hide handler between click-out and focus-in events hideHandler: function hideHandler(event) { var _this3 = this; var target = event.target; if (this.visible && !contains(this.$refs.menu, target) && !contains(this.toggler, target)) { this.clearHideTimeout(); this.$_hideTimeout = setTimeout(function () { return _this3.hide(); }, this.inNavbar ? 300 : 0); } }, // Document click-out listener clickOutHandler: function clickOutHandler(event) { this.hideHandler(event); }, // Document focus-in listener focusInHandler: function focusInHandler(event) { this.hideHandler(event); }, // Keyboard nav focusNext: function focusNext(event, up) { var _this4 = this; // Ignore key up/down on form elements var target = event.target; if (!this.visible || event && closest(SELECTOR_FORM_CHILD, target)) { /* istanbul ignore next: should never happen */ return; } stopEvent(event); this.$nextTick(function () { var items = _this4.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; } _this4.focusItem(index, items); }); }, focusItem: function focusItem(index, items) { var el = items.find(function (el, i) { return i === index; }); attemptFocus(el); }, getItems: function getItems() { // Get all items return filterVisibles(selectAll(SELECTOR_ITEM, this.$refs.menu)); }, focusMenu: function focusMenu() { attemptFocus(this.$refs.menu); }, focusToggler: function focusToggler() { var _this5 = this; this.$nextTick(function () { attemptFocus(_this5.toggler); }); } } }); var props$A = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$z), {}, { block: makeProp(PROP_TYPE_BOOLEAN, false), html: makeProp(PROP_TYPE_STRING), // If `true`, only render menu contents when open lazy: makeProp(PROP_TYPE_BOOLEAN, false), menuClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), noCaret: makeProp(PROP_TYPE_BOOLEAN, false), role: makeProp(PROP_TYPE_STRING, 'menu'), size: makeProp(PROP_TYPE_STRING), split: makeProp(PROP_TYPE_BOOLEAN, false), splitButtonType: makeProp(PROP_TYPE_STRING, 'button', function (value) { return arrayIncludes(['button', 'submit', 'reset'], value); }), splitClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), splitHref: makeProp(PROP_TYPE_STRING), splitTo: makeProp(PROP_TYPE_OBJECT_STRING), splitVariant: makeProp(PROP_TYPE_STRING), text: makeProp(PROP_TYPE_STRING), toggleClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), toggleTag: makeProp(PROP_TYPE_STRING, 'button'), // TODO: This really should be `toggleLabel` toggleText: makeProp(PROP_TYPE_STRING, 'Toggle dropdown'), variant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_DROPDOWN); // --- Main component --- // @vue/component var BDropdown = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN, mixins: [idMixin, dropdownMixin, normalizeSlotMixin], props: props$A, computed: { dropdownClasses: function dropdownClasses() { var block = this.block, split = this.split; return [this.directionClass, this.boundaryClass, { 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': split || !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': block && split }]; }, menuClasses: function menuClasses() { return [this.menuClass, { 'dropdown-menu-right': this.right, show: this.visible }]; }, toggleClasses: function toggleClasses() { var split = this.split; return [this.toggleClass, { 'dropdown-toggle-split': split, 'dropdown-toggle-no-caret': this.noCaret && !split }]; } }, render: function render(h) { var visible = this.visible, variant = this.variant, size = this.size, block = this.block, disabled = this.disabled, split = this.split, role = this.role, hide = this.hide, toggle = this.toggle; var commonProps = { variant: variant, size: size, block: block, disabled: disabled }; var $buttonChildren = this.normalizeSlot(SLOT_NAME_BUTTON_CONTENT); var buttonContentDomProps = this.hasNormalizedSlot(SLOT_NAME_BUTTON_CONTENT) ? {} : htmlOrText(this.html, this.text); var $split = h(); if (split) { var splitTo = this.splitTo, splitHref = this.splitHref, splitButtonType = this.splitButtonType; var btnProps = _objectSpread2(_objectSpread2({}, commonProps), {}, { variant: this.splitVariant || variant }); // We add these as needed due to <router-link> issues with // defined property with `undefined`/`null` values if (splitTo) { btnProps.to = splitTo; } else if (splitHref) { btnProps.href = splitHref; } else if (splitButtonType) { btnProps.type = splitButtonType; } $split = h(BButton, { class: this.splitClass, attrs: { id: this.safeId('_BV_button_') }, props: btnProps, domProps: buttonContentDomProps, on: { click: this.onSplitClick }, ref: 'button' }, $buttonChildren); // Overwrite button content for the toggle when in `split` mode $buttonChildren = [h('span', { class: ['sr-only'] }, [this.toggleText])]; buttonContentDomProps = {}; } var $toggle = h(BButton, { staticClass: 'dropdown-toggle', class: this.toggleClasses, attrs: { id: this.safeId('_BV_toggle_'), 'aria-haspopup': 'true', 'aria-expanded': toString$1(visible) }, props: _objectSpread2(_objectSpread2({}, commonProps), {}, { tag: this.toggleTag, block: block && !split }), domProps: buttonContentDomProps, on: { mousedown: this.onMousedown, click: toggle, keydown: toggle // Handle ENTER, SPACE and DOWN }, ref: 'toggle' }, $buttonChildren); var $menu = h('ul', { staticClass: 'dropdown-menu', class: this.menuClasses, attrs: { role: role, tabindex: '-1', 'aria-labelledby': this.safeId(split ? '_BV_button_' : '_BV_toggle_') }, on: { keydown: this.onKeydown // Handle UP, DOWN and ESC }, ref: 'menu' }, [!this.lazy || visible ? this.normalizeSlot(SLOT_NAME_DEFAULT, { hide: hide }) : h()]); return h('div', { staticClass: 'dropdown b-dropdown', class: this.dropdownClasses, attrs: { id: this.safeId() } }, [$split, $toggle, $menu]); } }); var linkProps$3 = omit(props$6, ['event', 'routerTag']); var props$B = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps$3), {}, { linkClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), variant: makeProp(PROP_TYPE_STRING) })), NAME_DROPDOWN_ITEM); // --- Main component --- // @vue/component var BDropdownItem = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_ITEM, mixins: [attrsMixin, normalizeSlotMixin], inject: { bvDropdown: { default: null } }, inheritAttrs: false, props: props$B, computed: { computedAttrs: function computedAttrs() { return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { role: 'menuitem' }); } }, 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(event) { this.$emit(EVENT_NAME_CLICK, event); this.closeDropdown(); } }, render: function render(h) { var linkClass = this.linkClass, variant = this.variant, active = this.active, disabled = this.disabled, onClick = this.onClick, bvAttrs = this.bvAttrs; return h('li', { class: bvAttrs.class, style: bvAttrs.style, attrs: { role: 'presentation' } }, [h(BLink, { staticClass: 'dropdown-item', class: [linkClass, _defineProperty({}, "text-".concat(variant), variant && !(active || disabled))], props: pluckProps(linkProps$3, this.$props), attrs: this.computedAttrs, on: { click: onClick }, ref: 'item' }, this.normalizeSlot())]); } }); var props$C = makePropsConfigurable({ active: makeProp(PROP_TYPE_BOOLEAN, false), activeClass: makeProp(PROP_TYPE_STRING, 'active'), buttonClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), disabled: makeProp(PROP_TYPE_BOOLEAN, false), variant: makeProp(PROP_TYPE_STRING) }, NAME_DROPDOWN_ITEM_BUTTON); // --- Main component --- // @vue/component var BDropdownItemButton = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_ITEM_BUTTON, mixins: [attrsMixin, normalizeSlotMixin], inject: { bvDropdown: { default: null } }, inheritAttrs: false, props: props$C, computed: { computedAttrs: function computedAttrs() { return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { role: 'menuitem', type: 'button', disabled: this.disabled }); } }, methods: { closeDropdown: function closeDropdown() { if (this.bvDropdown) { this.bvDropdown.hide(true); } }, onClick: function onClick(event) { this.$emit(EVENT_NAME_CLICK, event); this.closeDropdown(); } }, render: function render(h) { var _ref; var active = this.active, variant = this.variant, bvAttrs = this.bvAttrs; return h('li', { class: bvAttrs.class, style: bvAttrs.style, attrs: { role: 'presentation' } }, [h('button', { staticClass: 'dropdown-item', class: [this.buttonClass, (_ref = {}, _defineProperty(_ref, this.activeClass, active), _defineProperty(_ref, "text-".concat(variant), variant && !(active || this.disabled)), _ref)], attrs: this.computedAttrs, on: { click: this.onClick }, ref: 'button' }, this.normalizeSlot())]); } }); var props$D = makePropsConfigurable({ id: makeProp(PROP_TYPE_STRING), tag: makeProp(PROP_TYPE_STRING, 'header'), variant: makeProp(PROP_TYPE_STRING) }, NAME_DROPDOWN_HEADER); // --- Main component --- // @vue/component var BDropdownHeader = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_HEADER, functional: true, props: props$D, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var tag = props.tag, variant = props.variant; return h('li', a(omit(data, ['attrs']), { attrs: { role: 'presentation' } }), [h(tag, { staticClass: 'dropdown-header', class: _defineProperty({}, "text-".concat(variant), variant), attrs: _objectSpread2(_objectSpread2({}, data.attrs || {}), {}, { id: props.id || null, role: isTag(tag, 'header') ? null : 'heading' }), ref: 'header' }, children)]); } }); var props$E = makePropsConfigurable({ tag: makeProp(PROP_TYPE_STRING, 'hr') }, NAME_DROPDOWN_DIVIDER); // --- Main component --- // @vue/component var BDropdownDivider = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_DIVIDER, functional: true, props: props$E, render: function render(h, _ref) { var props = _ref.props, data = _ref.data; return h('li', a(omit(data, ['attrs']), { attrs: { role: 'presentation' } }), [h(props.tag, { staticClass: 'dropdown-divider', attrs: _objectSpread2(_objectSpread2({}, data.attrs || {}), {}, { role: 'separator', 'aria-orientation': 'horizontal' }), ref: 'divider' })]); } }); var props$F = makePropsConfigurable({ id: makeProp(PROP_TYPE_STRING), inline: makeProp(PROP_TYPE_BOOLEAN, false), novalidate: makeProp(PROP_TYPE_BOOLEAN, false), validated: makeProp(PROP_TYPE_BOOLEAN, false) }, NAME_FORM); // --- Main component --- // @vue/component var BForm = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM, functional: true, props: props$F, 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 props$G = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$F), {}, { disabled: makeProp(PROP_TYPE_BOOLEAN, false), formClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING) })), NAME_DROPDOWN_FORM); // --- Main component --- // @vue/component var BDropdownForm = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_FORM, functional: true, props: props$G, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, listeners = _ref.listeners, children = _ref.children; return h('li', a(omit(data, ['attrs', 'on']), { attrs: { role: 'presentation' } }), [h(BForm, { staticClass: 'b-dropdown-form', class: [props.formClass, { disabled: props.disabled }], props: props, attrs: _objectSpread2(_objectSpread2({}, data.attrs || {}), {}, { disabled: props.disabled, // Tab index of -1 for keyboard navigation tabindex: props.disabled ? null : '-1' }), on: listeners, ref: 'form' }, children)]); } }); var props$H = makePropsConfigurable({ tag: makeProp(PROP_TYPE_STRING, 'p'), textClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), variant: makeProp(PROP_TYPE_STRING) }, NAME_DROPDOWN_TEXT); // --- Main component --- // @vue/component var BDropdownText = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_TEXT, functional: true, props: props$H, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var tag = props.tag, textClass = props.textClass, variant = props.variant; return h('li', a(omit(data, ['attrs']), { attrs: { role: 'presentation' } }), [h(tag, { staticClass: 'b-dropdown-text', class: [textClass, _defineProperty({}, "text-".concat(variant), variant)], props: props, attrs: data.attrs || {}, ref: 'text' }, children)]); } }); var props$I = makePropsConfigurable({ ariaDescribedby: makeProp(PROP_TYPE_STRING), header: makeProp(PROP_TYPE_STRING), headerClasses: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), headerTag: makeProp(PROP_TYPE_STRING, 'header'), headerVariant: makeProp(PROP_TYPE_STRING), id: makeProp(PROP_TYPE_STRING) }, NAME_DROPDOWN_GROUP); // --- Main component --- // @vue/component var BDropdownGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_DROPDOWN_GROUP, functional: true, props: props$I, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, slots = _ref.slots, scopedSlots = _ref.scopedSlots; var id = props.id, variant = props.variant, header = props.header, headerTag = props.headerTag; var $slots = slots(); var $scopedSlots = scopedSlots || {}; var slotScope = {}; var headerId = id ? "_bv_".concat(id, "_group_dd_header") : null; var $header = h(); if (hasNormalizedSlot(SLOT_NAME_HEADER, $scopedSlots, $slots) || header) { $header = h(headerTag, { staticClass: 'dropdown-header', class: [props.headerClasses, _defineProperty({}, "text-".concat(variant), variant)], attrs: { id: headerId, role: isTag(headerTag, 'header') ? null : 'heading' } }, normalizeSlot(SLOT_NAME_HEADER, slotScope, $scopedSlots, $slots) || header); } return h('li', a(omit(data, ['attrs']), { attrs: { role: 'presentation' } }), [$header, h('ul', { staticClass: 'list-unstyled', attrs: _objectSpread2(_objectSpread2({}, data.attrs || {}), {}, { id: id, role: 'group', 'aria-describedby': [headerId, props.ariaDescribedBy].filter(identity).join(' ').trim() || null }) }, normalizeSlot(SLOT_NAME_DEFAULT, slotScope, $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 TYPES = ['iframe', 'embed', 'video', 'object', 'img', 'b-img', 'b-img-lazy']; // --- Props --- var props$J = makePropsConfigurable({ aspect: makeProp(PROP_TYPE_STRING, '16by9'), tag: makeProp(PROP_TYPE_STRING, 'div'), type: makeProp(PROP_TYPE_STRING, 'iframe', function (value) { return arrayIncludes(TYPES, value); }) }, NAME_EMBED); // --- Main component --- // @vue/component var BEmbed = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_EMBED, functional: true, props: props$J, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var aspect = props.aspect; return h(props.tag, { staticClass: 'embed-responsive', class: _defineProperty({}, "embed-responsive-".concat(aspect), aspect), ref: data.ref }, [h(props.type, a(omit(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.'; // --- Props --- var props$K = makePropsConfigurable({ disabledField: makeProp(PROP_TYPE_STRING, 'disabled'), htmlField: makeProp(PROP_TYPE_STRING, 'html'), options: makeProp(PROP_TYPE_ARRAY_OBJECT, []), textField: makeProp(PROP_TYPE_STRING, 'text'), valueField: makeProp(PROP_TYPE_STRING, 'value') }, 'formOptionControls'); // --- Mixin --- // @vue/component var formOptionsMixin = Vue__default['default'].extend({ props: props$K, computed: { formOptions: function formOptions() { return this.normalizeOptions(this.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); 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 }; }, normalizeOptions: function normalizeOptions(options) { var _this = this; // Normalize the given options array if (isArray(options)) { return options.map(function (option) { return _this.normalizeOption(option); }); } else if (isPlainObject(options)) { // 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); }); } // If not an array or object, return an empty array /* istanbul ignore next */ return []; } } }); var props$L = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$K), {}, { id: makeProp(PROP_TYPE_STRING, undefined, true) // Required })), NAME_FORM_DATALIST); // --- Main component --- // @vue/component var BFormDatalist = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_DATALIST, mixins: [formOptionsMixin, normalizeSlotMixin], props: props$L, render: function render(h) { var id = this.id; var $options = this.formOptions.map(function (option, index) { var value = option.value, text = option.text, html = option.html, disabled = option.disabled; return h('option', { attrs: { value: value, disabled: disabled }, domProps: htmlOrText(html, text), key: "option_".concat(index) }); }); return h('datalist', { attrs: { id: id } }, [$options, this.normalizeSlot()]); } }); var props$M = makePropsConfigurable({ id: makeProp(PROP_TYPE_STRING), inline: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'small'), textVariant: makeProp(PROP_TYPE_STRING, 'muted') }, NAME_FORM_TEXT); // --- Main component --- // @vue/component var BFormText = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_TEXT, functional: true, props: props$M, 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$N = makePropsConfigurable({ ariaLive: makeProp(PROP_TYPE_STRING), forceShow: makeProp(PROP_TYPE_BOOLEAN, false), id: makeProp(PROP_TYPE_STRING), role: makeProp(PROP_TYPE_STRING), // Tri-state prop: `true`, `false`, or `null` state: makeProp(PROP_TYPE_BOOLEAN, null), tag: makeProp(PROP_TYPE_STRING, 'div'), tooltip: makeProp(PROP_TYPE_BOOLEAN, false) }, NAME_FORM_INVALID_FEEDBACK); // --- Main component --- // @vue/component var BFormInvalidFeedback = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_INVALID_FEEDBACK, functional: true, props: props$N, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var tooltip = props.tooltip, ariaLive = props.ariaLive; var show = props.forceShow === true || props.state === false; return h(props.tag, a(data, { class: { 'd-block': show, 'invalid-feedback': !tooltip, 'invalid-tooltip': tooltip }, attrs: { id: props.id || null, role: props.role || null, 'aria-live': ariaLive || null, 'aria-atomic': ariaLive ? 'true' : null } }), children); } }); var props$O = makePropsConfigurable({ ariaLive: makeProp(PROP_TYPE_STRING), forceShow: makeProp(PROP_TYPE_BOOLEAN, false), id: makeProp(PROP_TYPE_STRING), role: makeProp(PROP_TYPE_STRING), // Tri-state prop: `true`, `false`, or `null` state: makeProp(PROP_TYPE_BOOLEAN, null), tag: makeProp(PROP_TYPE_STRING, 'div'), tooltip: makeProp(PROP_TYPE_BOOLEAN, false) }, NAME_FORM_VALID_FEEDBACK); // --- Main component --- // @vue/component var BFormValidFeedback = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_VALID_FEEDBACK, functional: true, props: props$O, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var tooltip = props.tooltip, ariaLive = props.ariaLive; var show = props.forceShow === true || props.state === true; return h(props.tag, a(data, { class: { 'd-block': show, 'valid-feedback': !tooltip, 'valid-tooltip': tooltip }, attrs: { id: props.id || null, role: props.role || null, 'aria-live': ariaLive || null, 'aria-atomic': ariaLive ? 'true' : null } }), children); } }); var props$P = makePropsConfigurable({ tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_FORM_ROW); // --- Main component --- // @vue/component var BFormRow = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_ROW, functional: true, props: props$P, 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(array, value) { for (var i = 0; i < array.length; i++) { if (looseEqual(array[i], value)) { return i; } } return -1; }; var SELECTOR = 'input, textarea, select'; // --- Props --- var props$Q = makePropsConfigurable({ autofocus: makeProp(PROP_TYPE_BOOLEAN, false), disabled: makeProp(PROP_TYPE_BOOLEAN, false), form: makeProp(PROP_TYPE_STRING), id: makeProp(PROP_TYPE_STRING), name: makeProp(PROP_TYPE_STRING), required: makeProp(PROP_TYPE_BOOLEAN, false) }, 'formControls'); // --- Mixin --- // @vue/component var formControlMixin = Vue__default['default'].extend({ props: props$Q, mounted: function mounted() { this.handleAutofocus(); }, /* istanbul ignore next */ activated: function activated() { 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); } attemptFocus(el); } }); }); } } }); var props$R = makePropsConfigurable({ plain: makeProp(PROP_TYPE_BOOLEAN, false) }, 'formControls'); // --- Mixin --- // @vue/component var formCustomMixin = Vue__default['default'].extend({ props: props$R, computed: { custom: function custom() { return !this.plain; } } }); var props$S = makePropsConfigurable({ size: makeProp(PROP_TYPE_STRING) }, 'formControls'); // --- Mixin --- // @vue/component var formSizeMixin = Vue__default['default'].extend({ props: props$S, computed: { sizeFormClass: function sizeFormClass() { return [this.size ? "form-control-".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 props$T = makePropsConfigurable({ // Tri-state prop: true, false, null (or undefined) state: makeProp(PROP_TYPE_BOOLEAN, null) }, 'formState'); // --- Mixin --- // @vue/component var formStateMixin = Vue__default['default'].extend({ props: props$T, 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; }, computedAriaInvalid: function computedAriaInvalid() { var ariaInvalid = this.ariaInvalid; if (ariaInvalid === true || ariaInvalid === 'true' || ariaInvalid === '') { return 'true'; } return this.computedState === false ? 'true' : ariaInvalid; } } }); var _watch$5, _methods; var _makeModelMixin$4 = makeModelMixin('checked', { defaultValue: null }), modelMixin$4 = _makeModelMixin$4.mixin, modelProps$4 = _makeModelMixin$4.props, MODEL_PROP_NAME$4 = _makeModelMixin$4.prop, MODEL_EVENT_NAME$4 = _makeModelMixin$4.event; var props$U = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$4), props$Q), props$S), props$T), props$R), {}, { ariaLabel: makeProp(PROP_TYPE_STRING), ariaLabelledby: makeProp(PROP_TYPE_STRING), // Only applicable in standalone mode (non group) button: makeProp(PROP_TYPE_BOOLEAN, false), // Only applicable when rendered with button style buttonVariant: makeProp(PROP_TYPE_STRING), inline: makeProp(PROP_TYPE_BOOLEAN, false), value: makeProp(PROP_TYPE_ANY) })), 'formRadioCheckControls'); // --- Mixin --- // @vue/component var formRadioCheckMixin = Vue__default['default'].extend({ mixins: [attrsMixin, idMixin, modelMixin$4, normalizeSlotMixin, formControlMixin, formSizeMixin, formStateMixin, formCustomMixin], inheritAttrs: false, props: props$U, data: function data() { return { localChecked: this.isGroup ? this.bvGroup[MODEL_PROP_NAME$4] : this[MODEL_PROP_NAME$4], hasFocus: false }; }, computed: { computedLocalChecked: { get: function get() { return this.isGroup ? this.bvGroup.localChecked : this.localChecked; }, set: function set(value) { if (this.isGroup) { this.bvGroup.localChecked = value; } else { this.localChecked = value; } } }, isChecked: function isChecked() { return looseEqual(this.value, this.computedLocalChecked); }, isRadio: function isRadio() { return true; }, isGroup: function isGroup() { // Is this check/radio a child of check-group or radio-group? return !!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.computedName && (this.isGroup ? this.bvGroup.required : this.required); }, computedName: function computedName() { // Group name preferred over local name return (this.isGroup ? this.bvGroup.groupName : this.name) || null; }, computedForm: function computedForm() { return (this.isGroup ? this.bvGroup.form : this.form) || null; }, computedSize: function computedSize() { return (this.isGroup ? this.bvGroup.size : this.size) || ''; }, computedState: function computedState() { return this.isGroup ? this.bvGroup.computedState : isBoolean(this.state) ? this.state : null; }, computedButtonVariant: function computedButtonVariant() { // Local variant preferred over group variant var buttonVariant = this.buttonVariant; if (buttonVariant) { return buttonVariant; } if (this.isGroup && this.bvGroup.buttonVariant) { return this.bvGroup.buttonVariant; } return 'secondary'; }, buttonClasses: function buttonClasses() { var _ref; var computedSize = this.computedSize; return ['btn', "btn-".concat(this.computedButtonVariant), (_ref = {}, _defineProperty(_ref, "btn-".concat(computedSize), computedSize), _defineProperty(_ref, "disabled", this.isDisabled), _defineProperty(_ref, "active", this.isChecked), _defineProperty(_ref, "focus", this.hasFocus), _ref)]; }, computedAttrs: function computedAttrs() { var disabled = this.isDisabled, required = this.isRequired; return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { id: this.safeId(), type: this.isRadio ? 'radio' : 'checkbox', name: this.computedName, form: this.computedForm, disabled: disabled, required: required, 'aria-required': required || null, 'aria-label': this.ariaLabel || null, 'aria-labelledby': this.ariaLabelledby || null }); } }, watch: (_watch$5 = {}, _defineProperty(_watch$5, MODEL_PROP_NAME$4, function () { this["".concat(MODEL_PROP_NAME$4, "Watcher")].apply(this, arguments); }), _defineProperty(_watch$5, "computedLocalChecked", function computedLocalChecked() { this.computedLocalCheckedWatcher.apply(this, arguments); }), _watch$5), methods: (_methods = {}, _defineProperty(_methods, "".concat(MODEL_PROP_NAME$4, "Watcher"), function Watcher(newValue) { if (!looseEqual(newValue, this.computedLocalChecked)) { this.computedLocalChecked = newValue; } }), _defineProperty(_methods, "computedLocalCheckedWatcher", function computedLocalCheckedWatcher(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(MODEL_EVENT_NAME$4, newValue); } }), _defineProperty(_methods, "handleChange", function handleChange(_ref2) { var _this = this; var checked = _ref2.target.checked; var value = this.value; var localChecked = checked ? value : null; this.computedLocalChecked = value; // Fire events in a `$nextTick()` to ensure the `v-model` is updated this.$nextTick(function () { // Change is only emitted on user interaction _this.$emit(EVENT_NAME_CHANGE, localChecked); // If this is a child of a group, we emit a change event on it as well if (_this.isGroup) { _this.bvGroup.$emit(EVENT_NAME_CHANGE, localChecked); } }); }), _defineProperty(_methods, "handleFocus", function handleFocus(event) { // 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 (event.target) { if (event.type === 'focus') { this.hasFocus = true; } else if (event.type === 'blur') { this.hasFocus = false; } } }), _defineProperty(_methods, "focus", function focus() { if (!this.isDisabled) { attemptFocus(this.$refs.input); } }), _defineProperty(_methods, "blur", function blur() { if (!this.isDisabled) { attemptBlur(this.$refs.input); } }), _methods), render: function render(h) { var isRadio = this.isRadio, isBtnMode = this.isBtnMode, isPlain = this.isPlain, isCustom = this.isCustom, isInline = this.isInline, isSwitch = this.isSwitch, computedSize = this.computedSize, bvAttrs = this.bvAttrs; var $content = this.normalizeSlot(); var $input = h('input', { class: [{ 'form-check-input': isPlain, 'custom-control-input': isCustom, // https://github.com/bootstrap-vue/bootstrap-vue/issues/2911 'position-static': isPlain && !$content }, isBtnMode ? '' : this.stateClass], directives: [{ name: 'model', value: this.computedLocalChecked }], attrs: this.computedAttrs, domProps: { value: this.value, checked: this.isChecked }, on: _objectSpread2({ change: this.handleChange }, isBtnMode ? { focus: this.handleFocus, blur: this.handleFocus } : {}), key: 'input', ref: 'input' }); if (isBtnMode) { var $button = h('label', { class: this.buttonClasses }, [$input, $content]); 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; } // If no label content in plain mode we dont render the label // See: https://github.com/bootstrap-vue/bootstrap-vue/issues/2911 var $label = h(); if (!(isPlain && !$content)) { $label = h('label', { class: { 'form-check-label': isPlain, 'custom-control-label': isCustom }, attrs: { for: this.safeId() } }, $content); } return h('div', { class: [_defineProperty({ 'form-check': isPlain, 'form-check-inline': isPlain && isInline, 'custom-control': isCustom, 'custom-control-inline': isCustom && isInline, 'custom-checkbox': isCustom && !isRadio && !isSwitch, 'custom-switch': isSwitch, 'custom-radio': isCustom && isRadio }, "b-custom-control-".concat(computedSize), computedSize && !isBtnMode), bvAttrs.class], style: bvAttrs.style }, [$input, $label]); } }); var _objectSpread2$1; var MODEL_PROP_NAME_INDETERMINATE = 'indeterminate'; var MODEL_EVENT_NAME_INDETERMINATE = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_INDETERMINATE; // --- Props --- var props$V = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$U), {}, (_objectSpread2$1 = {}, _defineProperty(_objectSpread2$1, MODEL_PROP_NAME_INDETERMINATE, makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_objectSpread2$1, "switch", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_objectSpread2$1, "uncheckedValue", makeProp(PROP_TYPE_ANY, false)), _defineProperty(_objectSpread2$1, "value", makeProp(PROP_TYPE_ANY, true)), _objectSpread2$1))), NAME_FORM_CHECKBOX); // --- Main component --- // @vue/component var BFormCheckbox = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_CHECKBOX, mixins: [formRadioCheckMixin], inject: { bvGroup: { from: 'bvCheckGroup', default: null } }, props: props$V, computed: { isChecked: function isChecked() { var value = this.value, checked = this.computedLocalChecked; return isArray(checked) ? looseIndexOf(checked, value) > -1 : looseEqual(checked, value); }, isRadio: function isRadio() { return false; } }, watch: _defineProperty({}, MODEL_PROP_NAME_INDETERMINATE, function (newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.setIndeterminate(newValue); } }), mounted: function mounted() { // Set initial indeterminate state this.setIndeterminate(this[MODEL_PROP_NAME_INDETERMINATE]); }, methods: { computedLocalCheckedWatcher: function computedLocalCheckedWatcher(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(MODEL_EVENT_NAME$4, newValue); var $input = this.$refs.input; if ($input) { this.$emit(MODEL_EVENT_NAME_INDETERMINATE, $input.indeterminate); } } }, handleChange: function handleChange(_ref) { var _this = this; var _ref$target = _ref.target, checked = _ref$target.checked, indeterminate = _ref$target.indeterminate; var value = this.value, uncheckedValue = this.uncheckedValue; // Update `computedLocalChecked` var localChecked = this.computedLocalChecked; if (isArray(localChecked)) { var index = looseIndexOf(localChecked, value); if (checked && index < 0) { // Add value to array localChecked = localChecked.concat(value); } else if (!checked && index > -1) { // Remove value from array localChecked = localChecked.slice(0, index).concat(localChecked.slice(index + 1)); } } else { localChecked = checked ? value : uncheckedValue; } this.computedLocalChecked = localChecked; // Fire events in a `$nextTick()` to ensure the `v-model` is updated this.$nextTick(function () { // Change is only emitted on user interaction _this.$emit(EVENT_NAME_CHANGE, localChecked); // If this is a child of a group, we emit a change event on it as well if (_this.isGroup) { _this.bvGroup.$emit(EVENT_NAME_CHANGE, localChecked); } _this.$emit(MODEL_EVENT_NAME_INDETERMINATE, indeterminate); }); }, setIndeterminate: function setIndeterminate(state) { // Indeterminate only supported in single checkbox mode if (isArray(this.computedLocalChecked)) { state = false; } var $input = this.$refs.input; if ($input) { $input.indeterminate = state; // Emit update event to prop this.$emit(MODEL_EVENT_NAME_INDETERMINATE, state); } } } }); var props$W = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$Q), props$U), props$S), props$T)), NAME_FORM_RADIO); // --- Main component --- // @vue/component var BFormRadio = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_RADIO, mixins: [idMixin, formRadioCheckMixin, // Includes shared render function formControlMixin, formSizeMixin, formStateMixin], inject: { bvGroup: { from: 'bvRadioGroup', default: false } }, props: props$W, watch: { computedLocalChecked: function computedLocalChecked(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(MODEL_EVENT_NAME$4, newValue); } } } }); var _watch$6; // Attributes to pass down to checks/radios instead of applying them to the group var PASS_DOWN_ATTRS = ['aria-describedby', 'aria-labelledby']; var _makeModelMixin$5 = makeModelMixin('checked'), modelMixin$5 = _makeModelMixin$5.mixin, modelProps$5 = _makeModelMixin$5.props, MODEL_PROP_NAME$5 = _makeModelMixin$5.prop, MODEL_EVENT_NAME$5 = _makeModelMixin$5.event; var props$X = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$5), props$Q), props$K), props$S), props$T), props$R), {}, { ariaInvalid: makeProp(PROP_TYPE_BOOLEAN_STRING, false), // Only applicable when rendered with button style buttonVariant: makeProp(PROP_TYPE_STRING), // Render as button style buttons: makeProp(PROP_TYPE_BOOLEAN, false), stacked: makeProp(PROP_TYPE_BOOLEAN, false), validated: makeProp(PROP_TYPE_BOOLEAN, false) })), 'formRadioCheckGroups'); // --- Mixin --- // @vue/component var formRadioCheckGroupMixin = Vue__default['default'].extend({ mixins: [idMixin, modelMixin$5, normalizeSlotMixin, formControlMixin, formOptionsMixin, formSizeMixin, formStateMixin, formCustomMixin], inheritAttrs: false, props: props$X, data: function data() { return { localChecked: this[MODEL_PROP_NAME$5] }; }, 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() { var inline = this.inline, size = this.size, validated = this.validated; var classes = { 'was-validated': validated }; if (this.buttons) { classes = [classes, 'btn-group-toggle', _defineProperty({ 'btn-group': inline, 'btn-group-vertical': !inline }, "btn-group-".concat(size), size)]; } return classes; } }, watch: (_watch$6 = {}, _defineProperty(_watch$6, MODEL_PROP_NAME$5, function (newValue) { if (!looseEqual(newValue, this.localChecked)) { this.localChecked = newValue; } }), _defineProperty(_watch$6, "localChecked", function localChecked(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(MODEL_EVENT_NAME$5, newValue); } }), _watch$6), render: function render(h) { var _this = this; var isRadioGroup = this.isRadioGroup; var attrs = pick(this.$attrs, PASS_DOWN_ATTRS); var optionComponent = isRadioGroup ? BFormRadio : BFormCheckbox; var $inputs = this.formOptions.map(function (option, index) { var key = "BV_option_".concat(index); return h(optionComponent, { props: { // Individual radios or checks can be disabled in a group disabled: option.disabled || false, id: _this.safeId(key), value: option.value // We don't need to include these, since the input's will know they are inside here // form: this.form || null, // name: this.groupName, // required: Boolean(this.name && this.required) }, attrs: attrs, key: key }, [h('span', { domProps: htmlOrText(option.html, option.text) })]); }); return h('div', { class: [this.groupClasses, 'bv-no-focus-ring'], attrs: _objectSpread2(_objectSpread2({}, omit(this.$attrs, PASS_DOWN_ATTRS)), {}, { 'aria-invalid': this.computedAriaInvalid, 'aria-required': this.required ? 'true' : null, id: this.safeId(), role: isRadioGroup ? 'radiogroup' : 'group', // Add `tabindex="-1"` to allow group to be focused if needed by screen readers tabindex: '-1' }) }, [this.normalizeSlot(SLOT_NAME_FIRST), $inputs, this.normalizeSlot()]); } }); var _objectSpread2$2; var props$Y = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$X), {}, (_objectSpread2$2 = {}, _defineProperty(_objectSpread2$2, MODEL_PROP_NAME$5, makeProp(PROP_TYPE_ARRAY, [])), _defineProperty(_objectSpread2$2, "switches", makeProp(PROP_TYPE_BOOLEAN, false)), _objectSpread2$2))), NAME_FORM_CHECKBOX_GROUP); // --- Main component --- // @vue/component var BFormCheckboxGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_CHECKBOX_GROUP, // Includes render function mixins: [formRadioCheckGroupMixin], provide: function provide() { return { bvCheckGroup: this }; }, props: props$Y, 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'; // --- Helper methods --- var createListener = function createListener(handler) { var listener = function listener(event) { handler(event.type === MOUSEENTER, event); }; 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 (IS_BROWSER) { 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 props$Z = sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$S), props$T), omit(props$z, ['disabled'])), omit(props$Q, ['autofocus'])), {}, { // When `true`, renders a `btn-group` wrapper and visually hides the label buttonOnly: makeProp(PROP_TYPE_BOOLEAN, false), // Applicable in button mode only buttonVariant: makeProp(PROP_TYPE_STRING, 'secondary'), // This is the value shown in the label // Defaults back to `value` formattedValue: makeProp(PROP_TYPE_STRING), // Value placed in `.sr-only` span inside label when value is present labelSelected: makeProp(PROP_TYPE_STRING), lang: makeProp(PROP_TYPE_STRING), // Extra classes to apply to the `dropdown-menu` div menuClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), // This is the value placed on the hidden input when no value selected placeholder: makeProp(PROP_TYPE_STRING), readonly: makeProp(PROP_TYPE_BOOLEAN, false), // Tri-state prop: `true`, `false` or `null` rtl: makeProp(PROP_TYPE_BOOLEAN, null), value: makeProp(PROP_TYPE_STRING, '') })); // --- Main component --- // @vue/component var BVFormBtnLabelControl = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_BUTTON_LABEL_CONTROL, directives: { 'b-hover': VBHover }, mixins: [idMixin, formSizeMixin, formStateMixin, dropdownMixin, normalizeSlotMixin], props: props$Z, 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) { attemptFocus(this.$refs.toggle); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$refs.toggle); } }, setFocus: function setFocus(event) { this.hasFocus = event.type === 'focus'; }, handleHover: function handleHover(hovered) { this.isHovered = hovered; } }, render: function render(h) { var _class; var idButton = this.idButton, idLabel = this.idLabel, idMenu = this.idMenu, idWrapper = this.idWrapper, disabled = this.disabled, readonly = this.readonly, required = this.required, name = this.name, state = this.state, visible = this.visible, size = this.size, isHovered = this.isHovered, hasFocus = this.hasFocus, labelSelected = this.labelSelected, buttonVariant = this.buttonVariant, buttonOnly = this.buttonOnly; var value = toString$1(this.value) || ''; var invalid = state === false || required && !value; var btnScope = { isHovered: isHovered, hasFocus: hasFocus, state: state, opened: visible }; var $button = h('button', { staticClass: 'btn', class: (_class = {}, _defineProperty(_class, "btn-".concat(buttonVariant), buttonOnly), _defineProperty(_class, "btn-".concat(size), size), _defineProperty(_class, 'h-auto', !buttonOnly), _defineProperty(_class, 'dropdown-toggle', buttonOnly), _defineProperty(_class, 'dropdown-toggle-no-caret', buttonOnly), _class), attrs: { id: idButton, type: 'button', disabled: disabled, 'aria-haspopup': 'dialog', 'aria-expanded': visible ? 'true' : 'false', 'aria-invalid': invalid ? '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 }, ref: 'toggle' }, [this.hasNormalizedSlot(SLOT_NAME_BUTTON_CONTENT) ? this.normalizeSlot(SLOT_NAME_BUTTON_CONTENT, btnScope) : /* istanbul ignore next */ h(BIconChevronDown, { props: { scale: 1.25 } })]); // Hidden input var $hidden = h(); if (name && !disabled) { $hidden = h('input', { attrs: { type: 'hidden', name: name || null, form: this.form || null, value: value } }); } // Dropdown content var $menu = h('div', { staticClass: 'dropdown-menu', 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 }, ref: 'menu' }, [this.normalizeSlot(SLOT_NAME_DEFAULT, { opened: visible })]); // Value label var $label = h('label', { class: buttonOnly ? 'sr-only' // Hidden in button only mode : ['form-control', // Mute the text if showing the placeholder { 'text-muted': !value }, this.stateClass, this.sizeFormClass], attrs: { id: idLabel, for: idButton, 'aria-invalid': invalid ? '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': /* istanbul ignore next */ function click(event) { stopEvent(event, { preventDefault: false }); } } }, [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 dropdown', class: [this.directionClass, this.boundaryClass, [{ 'btn-group': buttonOnly, 'form-control': !buttonOnly, focus: hasFocus && !buttonOnly, show: visible, 'is-valid': state === true, 'is-invalid': state === false }, buttonOnly ? null : this.sizeFormClass]], attrs: { id: idWrapper, role: buttonOnly ? null : '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 _watch$7; var _makeModelMixin$6 = makeModelMixin('value', { type: PROP_TYPE_DATE_STRING }), modelMixin$6 = _makeModelMixin$6.mixin, modelProps$6 = _makeModelMixin$6.props, MODEL_PROP_NAME$6 = _makeModelMixin$6.prop, MODEL_EVENT_NAME$6 = _makeModelMixin$6.event; // --- Props --- var calendarProps = omit(props$h, ['block', 'hidden', 'id', 'noKeyNav', 'roleDescription', 'value', 'width']); var formBtnLabelControlProps = omit(props$Z, ['formattedValue', 'id', 'lang', 'rtl', 'value']); var props$_ = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$6), calendarProps), formBtnLabelControlProps), {}, { // Width of the calendar dropdown calendarWidth: makeProp(PROP_TYPE_STRING, '270px'), closeButton: makeProp(PROP_TYPE_BOOLEAN, false), closeButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-secondary'), // Dark mode dark: makeProp(PROP_TYPE_BOOLEAN, false), labelCloseButton: makeProp(PROP_TYPE_STRING, 'Close'), labelResetButton: makeProp(PROP_TYPE_STRING, 'Reset'), labelTodayButton: makeProp(PROP_TYPE_STRING, 'Select today'), noCloseOnSelect: makeProp(PROP_TYPE_BOOLEAN, false), resetButton: makeProp(PROP_TYPE_BOOLEAN, false), resetButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-danger'), resetValue: makeProp(PROP_TYPE_DATE_STRING), todayButton: makeProp(PROP_TYPE_BOOLEAN, false), todayButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-primary') })), NAME_FORM_DATEPICKER); // --- Main component --- // @vue/component var BFormDatepicker = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_DATEPICKER, mixins: [idMixin, modelMixin$6], props: props$_, data: function data() { return { // We always use `YYYY-MM-DD` value internally localYMD: formatYMD(this[MODEL_PROP_NAME$6]) || '', // If the popup is open isVisible: false, // Context data from BCalendar localLocale: null, isRTL: false, formattedValue: '', activeYMD: '' }; }, 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); }, computedLang: function computedLang() { return (this.localLocale || '').replace(/-u-.*$/i, '') || null; }, computedResetValue: function computedResetValue() { return formatYMD(constrainDate(this.resetValue)) || ''; } }, watch: (_watch$7 = {}, _defineProperty(_watch$7, MODEL_PROP_NAME$6, function (newValue) { this.localYMD = formatYMD(newValue) || ''; }), _defineProperty(_watch$7, "localYMD", function localYMD(newValue) { // We only update the v-model when the datepicker is open if (this.isVisible) { this.$emit(MODEL_EVENT_NAME$6, this.valueAsDate ? parseYMD(newValue) || null : newValue || ''); } }), _defineProperty(_watch$7, "calendarYM", function calendarYM(newValue, oldValue) { // Displayed calendar month has changed // So possibly the calendar height has changed... // We need to update popper computed position if (newValue !== oldValue && oldValue) { try { this.$refs.control.updatePopper(); } catch (_unused) {} } }), _watch$7), methods: { // Public methods focus: function focus() { if (!this.disabled) { attemptFocus(this.$refs.control); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$refs.control); } }, // 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(EVENT_NAME_CONTEXT, ctx); }, onTodayButton: function onTodayButton() { // Set to today (or min/max if today is out of range) this.setAndClose(formatYMD(constrainDate(createDate(), this.min, this.max))); }, 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 () { attemptFocus(_this3.$refs.calendar); _this3.$emit(EVENT_NAME_SHOWN); }); }, onHidden: function onHidden() { this.isVisible = false; this.$emit(EVENT_NAME_HIDDEN); }, // Render helpers defaultButtonFn: function defaultButtonFn(_ref) { var isHovered = _ref.isHovered, hasFocus = _ref.hasFocus; return this.$createElement(isHovered || hasFocus ? BIconCalendarFill : BIconCalendar, { attrs: { 'aria-hidden': 'true' } }); } }, render: function render(h) { var localYMD = this.localYMD, disabled = this.disabled, readonly = this.readonly, dark = this.dark, $props = this.$props, $scopedSlots = this.$scopedSlots; 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: { disabled: disabled || readonly, size: 'sm', 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: { disabled: disabled || readonly, size: 'sm', 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: { disabled: disabled, size: 'sm', 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, { staticClass: 'b-form-date-calendar w-100', props: _objectSpread2(_objectSpread2({}, pluckProps(calendarProps, $props)), {}, { hidden: !this.isVisible, value: localYMD, valueAsDate: false, width: this.calendarWidth }), on: { selected: this.onSelected, input: this.onInput, context: this.onContext }, scopedSlots: pick($scopedSlots, ['nav-prev-decade', 'nav-prev-year', 'nav-prev-month', 'nav-this-month', 'nav-next-month', 'nav-next-year', 'nav-next-decade']), key: 'calendar', ref: 'calendar' }, $footer); return h(BVFormBtnLabelControl, { staticClass: 'b-form-datepicker', props: _objectSpread2(_objectSpread2({}, pluckProps(formBtnLabelControlProps, $props)), {}, { formattedValue: localYMD ? this.formattedValue : '', id: this.safeId(), lang: this.computedLang, menuClass: [{ 'bg-dark': dark, 'text-light': dark }, this.menuClass], placeholder: placeholder, rtl: this.isRTL, value: localYMD }), on: { show: this.onShow, shown: this.onShown, hidden: this.onHidden }, scopedSlots: _defineProperty({}, SLOT_NAME_BUTTON_CONTENT, $scopedSlots[SLOT_NAME_BUTTON_CONTENT] || this.defaultButtonFn), ref: 'control' }, [$calendar]); } }); var FormDatepickerPlugin = /*#__PURE__*/pluginFactory({ components: { BFormDatepicker: BFormDatepicker, BDatepicker: BFormDatepicker } }); var _watch$8; var _makeModelMixin$7 = makeModelMixin('value', { type: [PROP_TYPE_ARRAY, File], defaultValue: null, validator: function validator(value) { /* istanbul ignore next */ if (value === '') { warn(VALUE_EMPTY_DEPRECATED_MSG, NAME_FORM_FILE); return true; } return isUndefinedOrNull(value) || isValidValue(value); } }), modelMixin$7 = _makeModelMixin$7.mixin, modelProps$7 = _makeModelMixin$7.props, MODEL_PROP_NAME$7 = _makeModelMixin$7.prop, MODEL_EVENT_NAME$7 = _makeModelMixin$7.event; var VALUE_EMPTY_DEPRECATED_MSG = 'Setting "value"/"v-model" to an empty string for reset is deprecated. Set to "null" instead.'; // --- Helper methods --- var isValidValue = function isValidValue(value) { return isFile(value) || isArray(value) && value.every(function (v) { return isValidValue(v); }); }; // Helper method to "safely" get the entry from a data-transfer item /* istanbul ignore next: not supported in JSDOM */ var getDataTransferItemEntry = function getDataTransferItemEntry(item) { return isFunction(item.getAsEntry) ? item.getAsEntry() : isFunction(item.webkitGetAsEntry) ? item.webkitGetAsEntry() : null; }; // Drop handler function to get all files /* istanbul ignore next: not supported in JSDOM */ var getAllFileEntries = function getAllFileEntries(dataTransferItemList) { var traverseDirectories = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; return Promise.all(from(dataTransferItemList).filter(function (item) { return item.kind === 'file'; }).map(function (item) { var entry = getDataTransferItemEntry(item); if (entry) { if (entry.isDirectory && traverseDirectories) { return getAllFileEntriesInDirectory(entry.createReader(), "".concat(entry.name, "/")); } else if (entry.isFile) { return new Promise(function (resolve) { entry.file(function (file) { file.$path = ''; resolve(file); }); }); } } return null; }).filter(identity)); }; // Get all the file entries (recursive) in a directory /* istanbul ignore next: not supported in JSDOM */ var getAllFileEntriesInDirectory = function getAllFileEntriesInDirectory(directoryReader) { var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; return new Promise(function (resolve) { var entryPromises = []; var readDirectoryEntries = function readDirectoryEntries() { directoryReader.readEntries(function (entries) { if (entries.length === 0) { resolve(Promise.all(entryPromises).then(function (entries) { return flatten(entries); })); } else { entryPromises.push(Promise.all(entries.map(function (entry) { if (entry) { if (entry.isDirectory) { return getAllFileEntriesInDirectory(entry.createReader(), "".concat(path).concat(entry.name, "/")); } else if (entry.isFile) { return new Promise(function (resolve) { entry.file(function (file) { file.$path = "".concat(path).concat(file.name); resolve(file); }); }); } } return null; }).filter(identity))); readDirectoryEntries(); } }); }; readDirectoryEntries(); }); }; // --- Props --- var props$$ = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$7), props$Q), props$R), props$T), props$S), {}, { accept: makeProp(PROP_TYPE_STRING, ''), browseText: makeProp(PROP_TYPE_STRING, 'Browse'), // Instruct input to capture from camera capture: makeProp(PROP_TYPE_BOOLEAN, false), directory: makeProp(PROP_TYPE_BOOLEAN, false), dropPlaceholder: makeProp(PROP_TYPE_STRING, 'Drop files here'), fileNameFormatter: makeProp(PROP_TYPE_FUNCTION), multiple: makeProp(PROP_TYPE_BOOLEAN, false), noDrop: makeProp(PROP_TYPE_BOOLEAN, false), noDropPlaceholder: makeProp(PROP_TYPE_STRING, 'Not allowed'), // TODO: // Should we deprecate this and only support flat file structures? // Nested file structures are only supported when files are dropped // A Chromium "bug" prevents `webkitEntries` from being populated // on the file input's `change` event and is marked as "WontFix" // Mozilla implemented the behavior the same way as Chromium // See: https://bugs.chromium.org/p/chromium/issues/detail?id=138987 // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1326031 noTraverse: makeProp(PROP_TYPE_BOOLEAN, false), placeholder: makeProp(PROP_TYPE_STRING, 'No file chosen') })), NAME_FORM_FILE); // --- Main component --- // @vue/component var BFormFile = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_FILE, mixins: [attrsMixin, idMixin, modelMixin$7, normalizeSlotMixin, formControlMixin, formStateMixin, formCustomMixin, normalizeSlotMixin], inheritAttrs: false, props: props$$, data: function data() { return { files: [], dragging: false, // IE 11 doesn't respect setting `event.dataTransfer.dropEffect`, // so we handle it ourselves as well // https://stackoverflow.com/a/46915971/2744776 dropAllowed: !this.noDrop, hasFocus: false }; }, computed: { // Convert `accept` to an array of `[{ RegExpr, isMime }, ...]` computedAccept: function computedAccept() { var accept = this.accept; accept = (accept || '').trim().split(/[,\s]+/).filter(identity); // Allow any file type/extension if (accept.length === 0) { return null; } return accept.map(function (extOrType) { var prop = 'name'; var startMatch = '^'; var endMatch = '$'; if (RX_EXTENSION.test(extOrType)) { // File extension /\.ext$/ startMatch = ''; } else { // MIME type /^mime\/.+$/ or /^mime\/type$/ prop = 'type'; if (RX_STAR.test(extOrType)) { endMatch = '.+$'; // Remove trailing `*` extOrType = extOrType.slice(0, -1); } } // Escape all RegExp special chars extOrType = escapeRegExp(extOrType); var rx = new RegExp("".concat(startMatch).concat(extOrType).concat(endMatch)); return { rx: rx, prop: prop }; }); }, computedCapture: function computedCapture() { var capture = this.capture; return capture === true || capture === '' ? true : capture || null; }, computedAttrs: function computedAttrs() { var name = this.name, disabled = this.disabled, required = this.required, form = this.form, computedCapture = this.computedCapture, accept = this.accept, multiple = this.multiple, directory = this.directory; return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { type: 'file', id: this.safeId(), name: name, disabled: disabled, required: required, form: form || null, capture: computedCapture, accept: accept || null, multiple: multiple, directory: directory, webkitdirectory: directory, 'aria-required': required ? 'true' : null }); }, computedFileNameFormatter: function computedFileNameFormatter() { var fileNameFormatter = this.fileNameFormatter; return hasPropFunction(fileNameFormatter) ? fileNameFormatter : this.defaultFileNameFormatter; }, clonedFiles: function clonedFiles() { return cloneDeep(this.files); }, flattenedFiles: function flattenedFiles() { return flattenDeep(this.files); }, fileNames: function fileNames() { return this.flattenedFiles.map(function (file) { return file.name; }); }, labelContent: function labelContent() { // Draging active /* istanbul ignore next: used by drag/drop which can't be tested easily */ if (this.dragging && !this.noDrop) { return (// TODO: Add additional scope with file count, and other not-allowed reasons this.normalizeSlot(SLOT_NAME_DROP_PLACEHOLDER, { allowed: this.dropAllowed }) || (this.dropAllowed ? this.dropPlaceholder : this.$createElement('span', { staticClass: 'text-danger' }, this.noDropPlaceholder)) ); } // No file chosen if (this.files.length === 0) { return this.normalizeSlot(SLOT_NAME_PLACEHOLDER) || this.placeholder; } var flattenedFiles = this.flattenedFiles, clonedFiles = this.clonedFiles, fileNames = this.fileNames, computedFileNameFormatter = this.computedFileNameFormatter; // There is a slot for formatting the files/names if (this.hasNormalizedSlot(SLOT_NAME_FILE_NAME)) { return this.normalizeSlot(SLOT_NAME_FILE_NAME, { files: flattenedFiles, filesTraversed: clonedFiles, names: fileNames }); } return computedFileNameFormatter(flattenedFiles, clonedFiles, fileNames); } }, watch: (_watch$8 = {}, _defineProperty(_watch$8, MODEL_PROP_NAME$7, function (newValue) { if (!newValue || isArray(newValue) && newValue.length === 0) { this.reset(); } }), _defineProperty(_watch$8, "files", function files(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { var multiple = this.multiple, noTraverse = this.noTraverse; var files = !multiple || noTraverse ? flattenDeep(newValue) : newValue; this.$emit(MODEL_EVENT_NAME$7, multiple ? files : files[0] || null); } }), _watch$8), created: function created() { // Create private non-reactive props this.$_form = null; }, mounted: function mounted() { // Listen for form reset events, to reset the file input var $form = closest('form', this.$el); if ($form) { eventOn($form, 'reset', this.reset, EVENT_OPTIONS_PASSIVE); this.$_form = $form; } }, beforeDestroy: function beforeDestroy() { var $form = this.$_form; if ($form) { eventOff($form, 'reset', this.reset, EVENT_OPTIONS_PASSIVE); } }, methods: { isFileValid: function isFileValid(file) { if (!file) { return false; } var accept = this.computedAccept; return accept ? accept.some(function (a) { return a.rx.test(file[a.prop]); }) : true; }, isFilesArrayValid: function isFilesArrayValid(files) { var _this = this; return isArray(files) ? files.every(function (file) { return _this.isFileValid(file); }) : this.isFileValid(files); }, defaultFileNameFormatter: function defaultFileNameFormatter(flattenedFiles, clonedFiles, fileNames) { return fileNames.join(', '); }, setFiles: function setFiles(files) { // Reset the dragging flags this.dropAllowed = !this.noDrop; this.dragging = false; // Set the selected files this.files = this.multiple ? this.directory ? files : flattenDeep(files) : flattenDeep(files).slice(0, 1); }, /* istanbul ignore next: used by Drag/Drop */ setInputFiles: function setInputFiles(files) { // Try an set the file input files array so that `required` // constraint works for dropped files (will fail in IE11 though) // To be used only when dropping files try { // Firefox < 62 workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655 var dataTransfer = new ClipboardEvent('').clipboardData || new DataTransfer(); // Add flattened files to temp `dataTransfer` object to get a true `FileList` array flattenDeep(cloneDeep(files)).forEach(function (file) { // Make sure to remove the custom `$path` attribute delete file.$path; dataTransfer.items.add(file); }); this.$refs.input.files = dataTransfer.files; } catch (_unused) {} }, reset: function reset() { // 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 // Wrapped in try in case IE 11 or mobile Safari crap out try { var $input = this.$refs.input; $input.value = ''; $input.type = ''; $input.type = 'file'; } catch (_unused2) {} this.files = []; }, handleFiles: function handleFiles(files) { var isDrop = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; if (isDrop) { // When dropped, make sure to filter files with the internal `accept` logic var filteredFiles = files.filter(this.isFilesArrayValid); // Only update files when we have any after filtering if (filteredFiles.length > 0) { this.setFiles(filteredFiles); // Try an set the file input's files array so that `required` // constraint works for dropped files (will fail in IE 11 though) this.setInputFiles(filteredFiles); } } else { // We always update the files from the `change` event this.setFiles(files); } }, focusHandler: function focusHandler(event) { // 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 || event.type === 'focusout') { this.hasFocus = false; } else { // Add focus styling for custom file input this.hasFocus = true; } }, onChange: function onChange(event) { var _this2 = this; var type = event.type, target = event.target, _event$dataTransfer = event.dataTransfer, dataTransfer = _event$dataTransfer === void 0 ? {} : _event$dataTransfer; var isDrop = type === 'drop'; // Always emit original event this.$emit(EVENT_NAME_CHANGE, event); var items = from(dataTransfer.items || []); if (HAS_PROMISE_SUPPORT && items.length > 0 && !isNull(getDataTransferItemEntry(items[0]))) { // Drop handling for modern browsers // Supports nested directory structures in `directory` mode /* istanbul ignore next: not supported in JSDOM */ getAllFileEntries(items, this.directory).then(function (files) { return _this2.handleFiles(files, isDrop); }); } else { // Standard file input handling (native file input change event), // or fallback drop mode (IE 11 / Opera) which don't support `directory` mode var files = from(target.files || dataTransfer.files || []).map(function (file) { // Add custom `$path` property to each file (to be consistent with drop mode) file.$path = file.webkitRelativePath || ''; return file; }); this.handleFiles(files, isDrop); } }, onDragenter: function onDragenter(event) { stopEvent(event); this.dragging = true; var _event$dataTransfer2 = event.dataTransfer, dataTransfer = _event$dataTransfer2 === void 0 ? {} : _event$dataTransfer2; // Early exit when the input or dropping is disabled if (this.noDrop || this.disabled || !this.dropAllowed) { // Show deny feedback /* istanbul ignore next: not supported in JSDOM */ dataTransfer.dropEffect = 'none'; this.dropAllowed = false; return; } /* istanbul ignore next: not supported in JSDOM */ dataTransfer.dropEffect = 'copy'; }, // Note this event fires repeatedly while the mouse is over the dropzone at // intervals in the milliseconds, so avoid doing much processing in here onDragover: function onDragover(event) { stopEvent(event); this.dragging = true; var _event$dataTransfer3 = event.dataTransfer, dataTransfer = _event$dataTransfer3 === void 0 ? {} : _event$dataTransfer3; // Early exit when the input or dropping is disabled if (this.noDrop || this.disabled || !this.dropAllowed) { // Show deny feedback /* istanbul ignore next: not supported in JSDOM */ dataTransfer.dropEffect = 'none'; this.dropAllowed = false; return; } /* istanbul ignore next: not supported in JSDOM */ dataTransfer.dropEffect = 'copy'; }, onDragleave: function onDragleave(event) { var _this3 = this; stopEvent(event); this.$nextTick(function () { _this3.dragging = false; // Reset `dropAllowed` to default _this3.dropAllowed = !_this3.noDrop; }); }, // Triggered by a file drop onto drop target onDrop: function onDrop(event) { var _this4 = this; stopEvent(event); this.dragging = false; // Early exit when the input or dropping is disabled if (this.noDrop || this.disabled || !this.dropAllowed) { this.$nextTick(function () { // Reset `dropAllowed` to default _this4.dropAllowed = !_this4.noDrop; }); return; } this.onChange(event); } }, render: function render(h) { var custom = this.custom, plain = this.plain, size = this.size, dragging = this.dragging, stateClass = this.stateClass, bvAttrs = this.bvAttrs; // Form Input var $input = h('input', { class: [{ 'form-control-file': plain, 'custom-file-input': custom, focus: custom && this.hasFocus }, stateClass], // With IE 11, the input gets in the "way" of the drop events, // so we move it out of the way by putting it behind the label // Bootstrap v4 has it in front style: custom ? { zIndex: -5 } : {}, attrs: this.computedAttrs, on: { change: this.onChange, focusin: this.focusHandler, focusout: this.focusHandler, reset: this.reset }, ref: 'input' }); if (plain) { return $input; } // Overlay label var $label = h('label', { staticClass: 'custom-file-label', class: { dragging: dragging }, attrs: { for: this.safeId(), // This goes away in Bootstrap v5 'data-browse': this.browseText || null } }, [h('span', { staticClass: 'd-block form-file-text', // `pointer-events: none` is used to make sure // the drag events fire only on the label style: { pointerEvents: 'none' } }, [this.labelContent])]); // Return rendered custom file input return h('div', { staticClass: 'custom-file b-form-file', class: [_defineProperty({}, "b-custom-control-".concat(size), size), stateClass, bvAttrs.class], style: bvAttrs.style, attrs: { id: this.safeId('_BV_file_outer_') }, on: { dragenter: this.onDragenter, dragover: this.onDragover, dragleave: this.onDragleave, drop: this.onDrop } }, [$input, $label]); } }); var FormFilePlugin = /*#__PURE__*/pluginFactory({ components: { BFormFile: BFormFile, BFile: BFormFile } }); var escapeChar = function escapeChar(value) { return '\\' + value; }; // The `cssEscape()` util is based on this `CSS.escape()` polyfill: // https://github.com/mathiasbynens/CSS.escape var cssEscape = function cssEscape(value) { value = toString$1(value); var length = value.length; var firstCharCode = value.charCodeAt(0); return value.split('').reduce(function (result, char, index) { var charCode = value.charCodeAt(index); // If the character is NULL (U+0000), use (U+FFFD) as replacement if (charCode === 0x0000) { return result + "\uFFFD"; } // If the character ... if ( // ... is U+007F OR charCode === 0x007f || // ... is in the range [\1-\1F] (U+0001 to U+001F) OR ... charCode >= 0x0001 && charCode <= 0x001f || // ... is the first character and is in the range [0-9] (U+0030 to U+0039) OR ... index === 0 && charCode >= 0x0030 && charCode <= 0x0039 || // ... is the second character and is in the range [0-9] (U+0030 to U+0039) // and the first character is a `-` (U+002D) ... index === 1 && charCode >= 0x0030 && charCode <= 0x0039 && firstCharCode === 0x002d) { // ... https://drafts.csswg.org/cssom/#escape-a-character-as-code-point return result + escapeChar("".concat(charCode.toString(16), " ")); } // If the character ... if ( // ... is the first character AND ... index === 0 && // ... is a `-` (U+002D) AND ... charCode === 0x002d && // ... there is no second character ... length === 1) { // ... use the escaped character return result + escapeChar(char); } // If the character ... if ( // ... is greater than or equal to U+0080 OR ... charCode >= 0x0080 || // ... is `-` (U+002D) OR ... charCode === 0x002d || // ... is `_` (U+005F) OR ... charCode === 0x005f || // ... is in the range [0-9] (U+0030 to U+0039) OR ... charCode >= 0x0030 && charCode <= 0x0039 || // ... is in the range [A-Z] (U+0041 to U+005A) OR ... charCode >= 0x0041 && charCode <= 0x005a || // ... is in the range [a-z] (U+0061 to U+007A) ... charCode >= 0x0061 && charCode <= 0x007a) { // ... use the character itself return result + char; } // Otherwise use the escaped character // See: https://drafts.csswg.org/cssom/#escape-a-character return result + escapeChar(char); }, ''); }; var ALIGN_SELF_VALUES = ['auto', 'start', 'end', 'center', 'baseline', 'stretch']; // --- Helper methods --- // Compute a breakpoint class name var computeBreakpoint = function computeBreakpoint(type, breakpoint, value) { var className = type; if (isUndefinedOrNull(value) || value === 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`, '' indicates the prop's presence if (type === 'col' && (value === '' || value === true)) { // .col-md return lowerCase(className); } // .order-md-6 className += "-".concat(value); 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); // --- Props --- // Prop generator for lazy generation of props var generateProps = function generateProps() { // Grab the breakpoints from the cached config (exclude the '' (xs) breakpoint) var breakpoints = getBreakpointsUpCached().filter(identity); // i.e. 'col-sm', 'col-md-6', 'col-lg-auto', ... var breakpointCol = breakpoints.reduce(function (props, breakpoint) { props[breakpoint] = makeProp(PROP_TYPE_BOOLEAN_NUMBER_STRING); return props; }, create(null)); // i.e. 'offset-md-1', 'offset-lg-12', ... var breakpointOffset = breakpoints.reduce(function (props, breakpoint) { props[suffixPropName(breakpoint, 'offset')] = makeProp(PROP_TYPE_NUMBER_STRING); return props; }, create(null)); // i.e. 'order-md-1', 'order-lg-12', ... var breakpointOrder = breakpoints.reduce(function (props, breakpoint) { props[suffixPropName(breakpoint, 'order')] = makeProp(PROP_TYPE_NUMBER_STRING); return props; }, 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 makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, breakpointCol), breakpointOffset), breakpointOrder), {}, { // Flex alignment alignSelf: makeProp(PROP_TYPE_STRING, null, function (value) { return arrayIncludes(ALIGN_SELF_VALUES, value); }), // Generic flexbox 'col' (xs) col: makeProp(PROP_TYPE_BOOLEAN, false), // i.e. 'col-1', 'col-2', 'col-auto', ... cols: makeProp(PROP_TYPE_NUMBER_STRING), offset: makeProp(PROP_TYPE_NUMBER_STRING), order: makeProp(PROP_TYPE_NUMBER_STRING), tag: makeProp(PROP_TYPE_STRING, 'div') })), NAME_COL); }; // --- Main component --- // 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: NAME_COL, 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 cols = props.cols, offset = props.offset, order = props.order, alignSelf = props.alignSelf; 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 && !cols }, _defineProperty(_classList$push, "col-".concat(cols), cols), _defineProperty(_classList$push, "offset-".concat(offset), offset), _defineProperty(_classList$push, "order-".concat(order), order), _defineProperty(_classList$push, "align-self-".concat(alignSelf), alignSelf), _classList$push)); return h(props.tag, a(data, { class: classList }), children); } }; var INPUTS = ['input', 'select', 'textarea']; // Selector for finding first input in the form group var INPUT_SELECTOR = INPUTS.map(function (v) { return "".concat(v, ":not([disabled])"); }).join(); // A list of interactive elements (tag names) inside `<b-form-group>`'s legend var LEGEND_INTERACTIVE_ELEMENTS = [].concat(INPUTS, ['a', 'button', 'label']); // --- Props --- // Prop generator for lazy generation of props var generateProps$1 = function generateProps() { return makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$T), getBreakpointsUpCached().reduce(function (props, breakpoint) { // i.e. 'content-cols', 'content-cols-sm', 'content-cols-md', ... props[suffixPropName(breakpoint, 'contentCols')] = makeProp(PROP_TYPE_BOOLEAN_NUMBER_STRING); // i.e. 'label-align', 'label-align-sm', 'label-align-md', ... props[suffixPropName(breakpoint, 'labelAlign')] = makeProp(PROP_TYPE_STRING); // i.e. 'label-cols', 'label-cols-sm', 'label-cols-md', ... props[suffixPropName(breakpoint, 'labelCols')] = makeProp(PROP_TYPE_BOOLEAN_NUMBER_STRING); return props; }, create(null))), {}, { description: makeProp(PROP_TYPE_STRING), disabled: makeProp(PROP_TYPE_BOOLEAN, false), feedbackAriaLive: makeProp(PROP_TYPE_STRING, 'assertive'), invalidFeedback: makeProp(PROP_TYPE_STRING), label: makeProp(PROP_TYPE_STRING), labelClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), labelFor: makeProp(PROP_TYPE_STRING), labelSize: makeProp(PROP_TYPE_STRING), labelSrOnly: makeProp(PROP_TYPE_BOOLEAN, false), tooltip: makeProp(PROP_TYPE_BOOLEAN, false), validFeedback: makeProp(PROP_TYPE_STRING), validated: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_FORM_GROUP); }; // --- Main component --- // 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_FORM_GROUP, 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(); }, data: function data() { return { ariaDescribedby: null }; }, computed: { contentColProps: function contentColProps() { return this.getColProps(this.$props, 'content'); }, labelAlignClasses: function labelAlignClasses() { return this.getAlignClasses(this.$props, 'label'); }, labelColProps: function labelColProps() { return this.getColProps(this.$props, 'label'); }, isHorizontal: function isHorizontal() { // Determine if the form group will be rendered horizontal // based on the existence of 'content-col' or 'label-col' props return keys(this.contentColProps).length > 0 || keys(this.labelColProps).length > 0; } }, watch: { ariaDescribedby: function ariaDescribedby(newValue, oldValue) { if (newValue !== oldValue) { this.updateAriaDescribedby(newValue, oldValue); } } }, mounted: function mounted() { var _this = this; this.$nextTick(function () { // Set `aria-describedby` on the input specified by `labelFor` // We do this in a `$nextTick()` to ensure the children have finished rendering _this.updateAriaDescribedby(_this.ariaDescribedby); }); }, methods: { getAlignClasses: function getAlignClasses(props, prefix) { return getBreakpointsUpCached().reduce(function (result, breakpoint) { var propValue = props[suffixPropName(breakpoint, "".concat(prefix, "Align"))] || null; if (propValue) { result.push(['text', breakpoint, propValue].filter(identity).join('-')); } return result; }, []); }, getColProps: function getColProps(props, prefix) { return getBreakpointsUpCached().reduce(function (result, breakpoint) { var propValue = props[suffixPropName(breakpoint, "".concat(prefix, "Cols"))]; // Handle case where the prop's value is an empty string, // which represents `true` propValue = propValue === '' ? true : propValue || false; if (!isBoolean(propValue) && propValue !== 'auto') { // Convert to column size to number propValue = toInteger(propValue, 0); // Ensure column size is greater than `0` propValue = propValue > 0 ? propValue : false; } // Add the prop to the list of props to give to `<b-col>` // If breakpoint is '' (`${prefix}Cols` is `true`), then we use // the 'col' prop to make equal width at 'xs' if (propValue) { result[breakpoint || (isBoolean(propValue) ? 'col' : 'cols')] = propValue; } return result; }, {}); }, // Sets the `aria-describedby` attribute on the input if `labelFor` 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 updateAriaDescribedby: function updateAriaDescribedby(newValue, oldValue) { var labelFor = this.labelFor; if (IS_BROWSER && labelFor) { // We need to escape `labelFor` since it can be user-provided var $input = select("#".concat(cssEscape(labelFor)), this.$refs.content); if ($input) { var attr = 'aria-describedby'; var newIds = (newValue || '').split(RX_SPACE_SPLIT); var oldIds = (oldValue || '').split(RX_SPACE_SPLIT); // Update ID list, preserving any original IDs // and ensuring the ID's are unique var ids = (getAttr($input, attr) || '').split(RX_SPACE_SPLIT).filter(function (id) { return !arrayIncludes(oldIds, id); }).concat(newIds).filter(function (id, index, ids) { return ids.indexOf(id) === index; }).filter(identity).join(' ').trim(); if (ids) { setAttr($input, attr, ids); } else { removeAttr($input, attr); } } } }, onLegendClick: function onLegendClick(event) { // Don't do anything if `labelFor` is set /* istanbul ignore next: clicking a label will focus the input, so no need to test */ if (this.labelFor) { return; } var target = event.target; var tagName = target ? target.tagName : ''; // If clicked an interactive element inside legend, // we just let the default happen /* istanbul ignore next */ if (LEGEND_INTERACTIVE_ELEMENTS.indexOf(tagName) !== -1) { return; } // If only a single input, focus it, emulating label behaviour var inputs = selectAll(INPUT_SELECTOR, this.$refs.content).filter(isVisible); if (inputs.length === 1) { attemptFocus(inputs[0]); } } }, render: function render(h) { var state = this.computedState, feedbackAriaLive = this.feedbackAriaLive, isHorizontal = this.isHorizontal, labelFor = this.labelFor, normalizeSlot = this.normalizeSlot, safeId = this.safeId, tooltip = this.tooltip; var id = safeId(); var isFieldset = !labelFor; var $label = h(); var labelContent = normalizeSlot(SLOT_NAME_LABEL) || this.label; var labelId = labelContent ? safeId('_BV_label_') : null; if (labelContent || isHorizontal) { var labelSize = this.labelSize, labelColProps = this.labelColProps; var labelTag = isFieldset ? 'legend' : 'label'; if (this.labelSrOnly) { if (labelContent) { $label = h(labelTag, { class: 'sr-only', attrs: { id: labelId, for: labelFor || null } }, [labelContent]); } $label = h(isHorizontal ? BCol : 'div', { props: isHorizontal ? labelColProps : {} }, [$label]); } else { $label = h(isHorizontal ? BCol : labelTag, { on: isFieldset ? { click: this.onLegendClick } : {}, props: isHorizontal ? _objectSpread2(_objectSpread2({}, labelColProps), {}, { tag: labelTag }) : {}, attrs: { id: labelId, for: labelFor || null, // We add a `tabindex` to legend so that screen readers // will properly read the `aria-labelledby` in IE tabindex: isFieldset ? '-1' : null }, class: [// Hide the focus ring on the legend isFieldset ? 'bv-no-focus-ring' : '', // When horizontal or if a legend is rendered, add 'col-form-label' class // 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 || isFieldset ? 'col-form-label' : '', // Emulate label padding top of `0` on legend when not horizontal !isHorizontal && isFieldset ? 'pt-0' : '', // If not horizontal and not a legend, we add 'd-block' class to label // so that label-align works !isHorizontal && !isFieldset ? 'd-block' : '', labelSize ? "col-form-label-".concat(labelSize) : '', this.labelAlignClasses, this.labelClass] }, [labelContent]); } } var $invalidFeedback = h(); var invalidFeedbackContent = normalizeSlot(SLOT_NAME_INVALID_FEEDBACK) || this.invalidFeedback; var invalidFeedbackId = invalidFeedbackContent ? safeId('_BV_feedback_invalid_') : null; if (invalidFeedbackContent) { $invalidFeedback = h(BFormInvalidFeedback, { props: { ariaLive: feedbackAriaLive, id: invalidFeedbackId, role: feedbackAriaLive ? 'alert' : null, // If state is explicitly `false`, always show the feedback state: state, tooltip: tooltip }, attrs: { tabindex: invalidFeedbackContent ? '-1' : null } }, [invalidFeedbackContent]); } var $validFeedback = h(); var validFeedbackContent = normalizeSlot(SLOT_NAME_VALID_FEEDBACK) || this.validFeedback; var validFeedbackId = validFeedbackContent ? safeId('_BV_feedback_valid_') : null; if (validFeedbackContent) { $validFeedback = h(BFormValidFeedback, { props: { ariaLive: feedbackAriaLive, id: validFeedbackId, role: feedbackAriaLive ? 'alert' : null, // If state is explicitly `true`, always show the feedback state: state, tooltip: tooltip }, attrs: { tabindex: validFeedbackContent ? '-1' : null } }, [validFeedbackContent]); } var $description = h(); var descriptionContent = normalizeSlot(SLOT_NAME_DESCRIPTION) || this.description; var descriptionId = descriptionContent ? safeId('_BV_description_') : null; if (descriptionContent) { $description = h(BFormText, { attrs: { id: descriptionId, tabindex: '-1' } }, [descriptionContent]); } // Update `ariaDescribedby` // 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 var ariaDescribedby = this.ariaDescribedby = [descriptionId, state === false ? invalidFeedbackId : null, state === true ? validFeedbackId : null].filter(identity).join(' ') || null; var $content = h(isHorizontal ? BCol : 'div', { props: isHorizontal ? this.contentColProps : {}, ref: 'content' }, [normalizeSlot(SLOT_NAME_DEFAULT, { ariaDescribedby: ariaDescribedby, descriptionId: descriptionId, id: id, labelId: labelId }) || h(), $invalidFeedback, $validFeedback, $description]); // 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', { staticClass: 'form-group', class: [{ 'was-validated': this.validated }, this.stateClass], attrs: { id: id, disabled: isFieldset ? this.disabled : null, role: isFieldset ? null : 'group', 'aria-invalid': this.computedAriaInvalid, // 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 ? labelId : null } }, isHorizontal && isFieldset ? [h(BFormRow, [$label, $content])] : [$label, $content]); } }; var FormGroupPlugin = /*#__PURE__*/pluginFactory({ components: { BFormGroup: BFormGroup, BFormFieldset: BFormGroup } }); var formSelectionMixin = Vue__default['default'].extend({ computed: { selectionStart: { // Expose selectionStart for formatters, etc cache: false, /* istanbul ignore next */ get: function get() { return this.$refs.input.selectionStart; }, /* istanbul ignore next */ set: function set(val) { this.$refs.input.selectionStart = val; } }, selectionEnd: { // Expose selectionEnd for formatters, etc cache: false, /* istanbul ignore next */ get: function get() { return this.$refs.input.selectionEnd; }, /* istanbul ignore next */ set: function set(val) { this.$refs.input.selectionEnd = val; } }, selectionDirection: { // Expose selectionDirection for formatters, etc cache: false, /* istanbul ignore next */ get: function get() { return this.$refs.input.selectionDirection; }, /* istanbul ignore next */ set: function set(val) { this.$refs.input.selectionDirection = val; } } }, methods: { /* istanbul ignore next */ select: function select() { 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); }, /* istanbul ignore next */ setSelectionRange: function setSelectionRange() { 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); }, /* istanbul ignore next */ setRangeText: function setRangeText() { 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); } } }); var _makeModelMixin$8 = makeModelMixin('value', { type: PROP_TYPE_NUMBER_STRING, defaultValue: '', event: EVENT_NAME_UPDATE }), modelMixin$8 = _makeModelMixin$8.mixin, modelProps$8 = _makeModelMixin$8.props, MODEL_PROP_NAME$8 = _makeModelMixin$8.prop, MODEL_EVENT_NAME$8 = _makeModelMixin$8.event; var props$10 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, modelProps$8), {}, { ariaInvalid: makeProp(PROP_TYPE_BOOLEAN_STRING, false), autocomplete: makeProp(PROP_TYPE_STRING), // Debounce timeout (in ms). Not applicable with `lazy` prop debounce: makeProp(PROP_TYPE_NUMBER_STRING, 0), formatter: makeProp(PROP_TYPE_FUNCTION), // Only update the `v-model` on blur/change events lazy: makeProp(PROP_TYPE_BOOLEAN, false), lazyFormatter: makeProp(PROP_TYPE_BOOLEAN, false), number: makeProp(PROP_TYPE_BOOLEAN, false), placeholder: makeProp(PROP_TYPE_STRING), plaintext: makeProp(PROP_TYPE_BOOLEAN, false), readonly: makeProp(PROP_TYPE_BOOLEAN, false), trim: makeProp(PROP_TYPE_BOOLEAN, false) })), 'formTextControls'); // --- Mixin --- // @vue/component var formTextMixin = Vue__default['default'].extend({ mixins: [modelMixin$8], props: props$10, data: function data() { var value = this[MODEL_PROP_NAME$8]; return { localValue: toString$1(value), vModelValue: this.modifyValue(value) }; }, computed: { computedClass: function computedClass() { var plaintext = this.plaintext, type = this.type; var isRange = type === 'range'; var isColor = type === 'color'; return [{ // Range input needs class `custom-range` 'custom-range': isRange, // `plaintext` not supported by `type="range"` or `type="color"` 'form-control-plaintext': plaintext && !isRange && !isColor, // `form-control` not used by `type="range"` or `plaintext` // Always used by `type="color"` 'form-control': isColor || !plaintext && !isRange }, this.sizeFormClass, this.stateClass]; }, computedDebounce: function computedDebounce() { // Ensure we have a positive number equal to or greater than 0 return mathMax(toInteger(this.debounce, 0), 0); }, hasFormatter: function hasFormatter() { return hasPropFunction(this.formatter); } }, watch: _defineProperty({}, MODEL_PROP_NAME$8, function (newValue) { var stringifyValue = toString$1(newValue); var modifiedValue = this.modifyValue(newValue); if (stringifyValue !== this.localValue || modifiedValue !== 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 = modifiedValue; } }), created: function created() { // Create private non-reactive props this.$_inputDebounceTimer = null; }, mounted: function mounted() { // Set up destroy handler this.$on(HOOK_EVENT_NAME_BEFORE_DESTROY, this.clearDebounce); }, beforeDestroy: function beforeDestroy() { this.clearDebounce(); }, methods: { clearDebounce: function clearDebounce() { clearTimeout(this.$_inputDebounceTimer); this.$_inputDebounceTimer = null; }, formatValue: function formatValue(value, event) { 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, event); } return value; }, modifyValue: function modifyValue(value) { value = toString$1(value); // Emulate `.trim` modifier behaviour if (this.trim) { value = value.trim(); } // Emulate `.number` modifier behaviour if (this.number) { value = toFloat(value, value); } 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; } // Make sure to always clear the debounce when `updateValue()` // is called, even when the v-model hasn't changed this.clearDebounce(); // Define the shared update logic in a method to be able to use // it for immediate and debounced value changes var doUpdate = function doUpdate() { value = _this.modifyValue(value); if (value !== _this.vModelValue) { _this.vModelValue = value; _this.$emit(MODEL_EVENT_NAME$8, value); } 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; } } }; // 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 var debounce = this.computedDebounce; if (debounce > 0 && !lazy && !force) { this.$_inputDebounceTimer = setTimeout(doUpdate, debounce); } else { // Immediately update the v-model doUpdate(); } }, onInput: function onInput(event) { // `event.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 (event.target.composing) { return; } var value = event.target.value; var formattedValue = this.formatValue(value, event); // Exit when the `formatter` function strictly returned `false` // or prevented the input event /* istanbul ignore next */ if (formattedValue === false || event.defaultPrevented) { stopEvent(event, { propagation: false }); return; } this.localValue = formattedValue; this.updateValue(formattedValue); this.$emit(EVENT_NAME_INPUT, formattedValue); }, onChange: function onChange(event) { var value = event.target.value; var formattedValue = this.formatValue(value, event); // Exit when the `formatter` function strictly returned `false` // or prevented the input event /* istanbul ignore next */ if (formattedValue === false || event.defaultPrevented) { stopEvent(event, { propagation: false }); return; } this.localValue = formattedValue; this.updateValue(formattedValue, true); this.$emit(EVENT_NAME_CHANGE, formattedValue); }, onBlur: function onBlur(event) { // Apply the `localValue` on blur to prevent cursor jumps // on mobile browsers (e.g. caused by autocomplete) var value = event.target.value; var formattedValue = this.formatValue(value, event, 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(EVENT_NAME_BLUR, event); }, focus: function focus() { // For external handler that may want a focus method if (!this.disabled) { attemptFocus(this.$el); } }, blur: function blur() { // For external handler that may want a blur method if (!this.disabled) { attemptBlur(this.$el); } } } }); var formValidityMixin = Vue__default['default'].extend({ computed: { validity: { // Expose validity property cache: false, /* istanbul ignore next */ get: function get() { return this.$refs.input.validity; } }, validationMessage: { // Expose validationMessage property cache: false, /* istanbul ignore next */ get: function get() { return this.$refs.input.validationMessage; } }, willValidate: { // Expose willValidate property cache: false, /* istanbul ignore next */ get: function get() { return this.$refs.input.willValidate; } } }, methods: { /* istanbul ignore next */ setCustomValidity: function setCustomValidity() { 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); }, /* istanbul ignore next */ checkValidity: function checkValidity() { 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); }, /* istanbul ignore next */ reportValidity: function reportValidity() { 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); } } }); // Valid supported input types var TYPES$1 = ['text', 'password', 'email', 'number', 'url', 'tel', 'search', 'range', 'color', 'date', 'time', 'datetime', 'datetime-local', 'month', 'week']; // --- Props --- var props$11 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$Q), props$S), props$T), props$10), {}, { list: makeProp(PROP_TYPE_STRING), max: makeProp(PROP_TYPE_NUMBER_STRING), min: makeProp(PROP_TYPE_NUMBER_STRING), // Disable mousewheel to prevent wheel from changing values (i.e. number/date) noWheel: makeProp(PROP_TYPE_BOOLEAN, false), step: makeProp(PROP_TYPE_NUMBER_STRING), type: makeProp(PROP_TYPE_STRING, 'text', function (type) { return arrayIncludes(TYPES$1, type); }) })), NAME_FORM_INPUT); // --- Main component --- // @vue/component var BFormInput = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_INPUT, // Mixin order is important! mixins: [listenersMixin, idMixin, formControlMixin, formSizeMixin, formStateMixin, formTextMixin, formSelectionMixin, formValidityMixin], props: props$11, computed: { localType: function localType() { // We only allow certain types var type = this.type; return arrayIncludes(TYPES$1, type) ? type : 'text'; }, computedAttrs: function computedAttrs() { var type = this.localType, name = this.name, form = this.form, disabled = this.disabled, placeholder = this.placeholder, required = this.required, min = this.min, max = this.max, step = this.step; return { id: this.safeId(), name: name, form: form, type: type, disabled: disabled, placeholder: placeholder, required: required, autocomplete: this.autocomplete || null, readonly: this.readonly || this.plaintext, min: min, max: max, step: step, list: type !== 'password' ? this.list : null, 'aria-required': required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid }; }, computedListeners: function computedListeners() { return _objectSpread2(_objectSpread2({}, this.bvListeners), {}, { input: this.onInput, change: this.onChange, blur: this.onBlur }); } }, watch: { noWheel: function noWheel(newValue) { this.setWheelStopper(newValue); } }, mounted: function mounted() { this.setWheelStopper(this.noWheel); }, /* istanbul ignore next */ deactivated: function deactivated() { // Turn off listeners when keep-alive component deactivated /* istanbul ignore next */ this.setWheelStopper(false); }, /* istanbul ignore next */ 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(event) { stopEvent(event, { propagation: false }); attemptBlur(this.$el); } }, render: function render(h) { return h('input', { class: this.computedClass, attrs: this.computedAttrs, domProps: { value: this.localValue }, on: this.computedListeners, ref: 'input' }); } }); var FormInputPlugin = /*#__PURE__*/pluginFactory({ components: { BFormInput: BFormInput, BInput: BFormInput } }); var props$12 = makePropsConfigurable(props$X, NAME_FORM_RADIO_GROUP); // --- Main component --- // @vue/component var BFormRadioGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_RADIO_GROUP, mixins: [formRadioCheckGroupMixin], provide: function provide() { return { bvRadioGroup: this }; }, props: props$12, computed: { isRadioGroup: function isRadioGroup() { return true; } } }); var FormRadioPlugin = /*#__PURE__*/pluginFactory({ components: { BFormRadio: BFormRadio, BRadio: BFormRadio, BFormRadioGroup: BFormRadioGroup, BRadioGroup: BFormRadioGroup } }); var _watch$9; var _makeModelMixin$9 = makeModelMixin('value', { type: PROP_TYPE_NUMBER_STRING, event: EVENT_NAME_CHANGE }), modelMixin$9 = _makeModelMixin$9.mixin, modelProps$9 = _makeModelMixin$9.props, MODEL_PROP_NAME$9 = _makeModelMixin$9.prop, MODEL_EVENT_NAME$9 = _makeModelMixin$9.event; var MIN_STARS = 3; var DEFAULT_STARS = 5; // --- Helper methods --- var computeStars = function computeStars(stars) { return mathMax(MIN_STARS, toInteger(stars, DEFAULT_STARS)); }; var clampValue = function clampValue(value, min, max) { return mathMax(mathMin(value, max), min); }; // --- Helper components --- // @vue/component var BVFormRatingStar = Vue__default['default'].extend({ name: NAME_FORM_RATING_STAR, mixins: [normalizeSlotMixin], props: { disabled: makeProp(PROP_TYPE_BOOLEAN, false), // If parent is focused focused: makeProp(PROP_TYPE_BOOLEAN, false), hasClear: makeProp(PROP_TYPE_BOOLEAN, false), rating: makeProp(PROP_TYPE_NUMBER, 0), readonly: makeProp(PROP_TYPE_BOOLEAN, false), star: makeProp(PROP_TYPE_NUMBER, 0), variant: makeProp(PROP_TYPE_STRING) }, methods: { onClick: function onClick(event) { if (!this.disabled && !this.readonly) { stopEvent(event, { propagation: false }); this.$emit(EVENT_NAME_SELECTED, this.star); } } }, render: function render(h) { var rating = this.rating, star = this.star, focused = this.focused, hasClear = this.hasClear, variant = this.variant, disabled = this.disabled, readonly = this.readonly; var minStar = hasClear ? 0 : 1; var type = rating >= star ? 'full' : rating >= star - 0.5 ? 'half' : 'empty'; var slotScope = { variant: variant, disabled: disabled, readonly: readonly }; return h('span', { staticClass: 'b-rating-star', class: { // When not hovered, we use this class to focus the current (or first) star focused: focused && rating === star || !toInteger(rating) && star === minStar, // We add type classes to we can handle RTL styling 'b-rating-star-empty': type === 'empty', 'b-rating-star-half': type === 'half', 'b-rating-star-full': type === 'full' }, attrs: { tabindex: !disabled && !readonly ? '-1' : null }, on: { click: this.onClick } }, [h('span', { staticClass: 'b-rating-icon' }, [this.normalizeSlot(type, slotScope)])]); } }); // --- Props --- var props$13 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$9), omit(props$Q, ['required', 'autofocus'])), props$S), {}, { // CSS color string (overrides variant) color: makeProp(PROP_TYPE_STRING), iconClear: makeProp(PROP_TYPE_STRING, 'x'), iconEmpty: makeProp(PROP_TYPE_STRING, 'star'), iconFull: makeProp(PROP_TYPE_STRING, 'star-fill'), iconHalf: makeProp(PROP_TYPE_STRING, 'star-half'), inline: makeProp(PROP_TYPE_BOOLEAN, false), // Locale for the formatted value (if shown) // Defaults to the browser locale. Falls back to `en` locale: makeProp(PROP_TYPE_ARRAY_STRING), noBorder: makeProp(PROP_TYPE_BOOLEAN, false), precision: makeProp(PROP_TYPE_NUMBER_STRING), readonly: makeProp(PROP_TYPE_BOOLEAN, false), showClear: makeProp(PROP_TYPE_BOOLEAN, false), showValue: makeProp(PROP_TYPE_BOOLEAN, false), showValueMax: makeProp(PROP_TYPE_BOOLEAN, false), stars: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_STARS, function (value) { return toInteger(value) >= MIN_STARS; }), variant: makeProp(PROP_TYPE_STRING) })), NAME_FORM_RATING); // --- Main component --- // @vue/component var BFormRating = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_RATING, components: { BIconStar: BIconStar, BIconStarHalf: BIconStarHalf, BIconStarFill: BIconStarFill, BIconX: BIconX }, mixins: [idMixin, modelMixin$9, formSizeMixin], props: props$13, data: function data() { var value = toFloat(this[MODEL_PROP_NAME$9], null); var stars = computeStars(this.stars); return { localValue: isNull(value) ? null : clampValue(value, 0, stars), hasFocus: false }; }, computed: { computedStars: function computedStars() { return computeStars(this.stars); }, computedRating: function computedRating() { var value = toFloat(this.localValue, 0); var precision = toInteger(this.precision, 3); // We clamp the value between `0` and stars return clampValue(toFloat(value.toFixed(precision)), 0, this.computedStars); }, computedLocale: function computedLocale() { var locales = concat(this.locale).filter(identity); var nf = new Intl.NumberFormat(locales); return nf.resolvedOptions().locale; }, isInteractive: function isInteractive() { return !this.disabled && !this.readonly; }, isRTL: function isRTL() { return isLocaleRTL(this.computedLocale); }, formattedRating: function formattedRating() { var precision = toInteger(this.precision); var showValueMax = this.showValueMax; var locale = this.computedLocale; var formatOptions = { notation: 'standard', minimumFractionDigits: isNaN(precision) ? 0 : precision, maximumFractionDigits: isNaN(precision) ? 3 : precision }; var stars = this.computedStars.toLocaleString(locale); var value = this.localValue; value = isNull(value) ? showValueMax ? '-' : '' : value.toLocaleString(locale, formatOptions); return showValueMax ? "".concat(value, "/").concat(stars) : value; } }, watch: (_watch$9 = {}, _defineProperty(_watch$9, MODEL_PROP_NAME$9, function (newValue, oldValue) { if (newValue !== oldValue) { var value = toFloat(newValue, null); this.localValue = isNull(value) ? null : clampValue(value, 0, this.computedStars); } }), _defineProperty(_watch$9, "localValue", function localValue(newValue, oldValue) { if (newValue !== oldValue && newValue !== (this.value || 0)) { this.$emit(MODEL_EVENT_NAME$9, newValue || null); } }), _defineProperty(_watch$9, "disabled", function disabled(newValue) { if (newValue) { this.hasFocus = false; this.blur(); } }), _watch$9), methods: { // --- Public methods --- focus: function focus() { if (!this.disabled) { attemptFocus(this.$el); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$el); } }, // --- Private methods --- onKeydown: function onKeydown(event) { var keyCode = event.keyCode; if (this.isInteractive && arrayIncludes([CODE_LEFT, CODE_DOWN, CODE_RIGHT, CODE_UP], keyCode)) { stopEvent(event, { propagation: false }); var value = toInteger(this.localValue, 0); var min = this.showClear ? 0 : 1; var stars = this.computedStars; // In RTL mode, LEFT/RIGHT are swapped var amountRtl = this.isRTL ? -1 : 1; if (keyCode === CODE_LEFT) { this.localValue = clampValue(value - amountRtl, min, stars) || null; } else if (keyCode === CODE_RIGHT) { this.localValue = clampValue(value + amountRtl, min, stars); } else if (keyCode === CODE_DOWN) { this.localValue = clampValue(value - 1, min, stars) || null; } else if (keyCode === CODE_UP) { this.localValue = clampValue(value + 1, min, stars); } } }, onSelected: function onSelected(value) { if (this.isInteractive) { this.localValue = value; } }, onFocus: function onFocus(event) { this.hasFocus = !this.isInteractive ? false : event.type === 'focus'; }, // --- Render methods --- renderIcon: function renderIcon(icon) { return this.$createElement(BIcon, { props: { icon: icon, variant: this.disabled || this.color ? null : this.variant || null } }); }, iconEmptyFn: function iconEmptyFn() { return this.renderIcon(this.iconEmpty); }, iconHalfFn: function iconHalfFn() { return this.renderIcon(this.iconHalf); }, iconFullFn: function iconFullFn() { return this.renderIcon(this.iconFull); }, iconClearFn: function iconClearFn() { return this.$createElement(BIcon, { props: { icon: this.iconClear } }); } }, render: function render(h) { var _this = this; var disabled = this.disabled, readonly = this.readonly, name = this.name, form = this.form, inline = this.inline, variant = this.variant, color = this.color, noBorder = this.noBorder, hasFocus = this.hasFocus, computedRating = this.computedRating, computedStars = this.computedStars, formattedRating = this.formattedRating, showClear = this.showClear, isRTL = this.isRTL, isInteractive = this.isInteractive, $scopedSlots = this.$scopedSlots; var $content = []; if (showClear && !disabled && !readonly) { var $icon = h('span', { staticClass: 'b-rating-icon' }, [($scopedSlots[SLOT_NAME_ICON_CLEAR] || this.iconClearFn)()]); $content.push(h('span', { staticClass: 'b-rating-star b-rating-star-clear flex-grow-1', class: { focused: hasFocus && computedRating === 0 }, attrs: { tabindex: isInteractive ? '-1' : null }, on: { click: function click() { return _this.onSelected(null); } }, key: 'clear' }, [$icon])); } for (var index = 0; index < computedStars; index++) { var value = index + 1; $content.push(h(BVFormRatingStar, { staticClass: 'flex-grow-1', style: color && !disabled ? { color: color } : {}, props: { rating: computedRating, star: value, variant: disabled ? null : variant || null, disabled: disabled, readonly: readonly, focused: hasFocus, hasClear: showClear }, on: { selected: this.onSelected }, scopedSlots: { empty: $scopedSlots[SLOT_NAME_ICON_EMPTY] || this.iconEmptyFn, half: $scopedSlots[SLOT_NAME_ICON_HALF] || this.iconHalfFn, full: $scopedSlots[SLOT_NAME_ICON_FULL] || this.iconFullFn }, key: index })); } if (name) { $content.push(h('input', { attrs: { type: 'hidden', value: isNull(this.localValue) ? '' : computedRating, name: name, form: form || null }, key: 'hidden' })); } if (this.showValue) { $content.push(h('b', { staticClass: 'b-rating-value flex-grow-1', attrs: { 'aria-hidden': 'true' }, key: 'value' }, toString$1(formattedRating))); } return h('output', { staticClass: 'b-rating form-control align-items-center', class: [{ 'd-inline-flex': inline, 'd-flex': !inline, 'border-0': noBorder, disabled: disabled, readonly: !disabled && readonly }, this.sizeFormClass], attrs: { id: this.safeId(), dir: isRTL ? 'rtl' : 'ltr', tabindex: disabled ? null : '0', disabled: disabled, role: 'slider', 'aria-disabled': disabled ? 'true' : null, 'aria-readonly': !disabled && readonly ? 'true' : null, 'aria-live': 'off', 'aria-valuemin': showClear ? '0' : '1', 'aria-valuemax': toString$1(computedStars), 'aria-valuenow': computedRating ? toString$1(computedRating) : null }, on: { keydown: this.onKeydown, focus: this.onFocus, blur: this.onFocus } }, $content); } }); var FormRatingPlugin = /*#__PURE__*/pluginFactory({ components: { BFormRating: BFormRating, BRating: BFormRating } }); var _makeModelMixin$a = makeModelMixin('value'), mixin = _makeModelMixin$a.mixin, props$14 = _makeModelMixin$a.props, prop = _makeModelMixin$a.prop, event = _makeModelMixin$a.event; var props$15 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$K), {}, { labelField: makeProp(PROP_TYPE_STRING, 'label'), optionsField: makeProp(PROP_TYPE_STRING, 'options') })), 'formOptions'); // --- Mixin --- // @vue/component var optionsMixin = Vue__default['default'].extend({ mixins: [formOptionsMixin], props: props$15, 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, null); // When it has options, create an `<optgroup>` object if (!isNull(options)) { return { label: String(get(option, this.labelField) || text), options: this.normalizeOptions(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 props$16 = makePropsConfigurable({ disabled: makeProp(PROP_TYPE_BOOLEAN, false), value: makeProp(PROP_TYPE_ANY, undefined, true) // Required }, NAME_FORM_SELECT_OPTION); // --- Main component --- // @vue/component var BFormSelectOption = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_SELECT_OPTION, functional: true, props: props$16, 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 props$17 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$K), {}, { label: makeProp(PROP_TYPE_STRING, undefined, true) // Required })), NAME_FORM_SELECT_OPTION_GROUP); // --- Main component --- // @vue/component var BFormSelectOptionGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_SELECT_OPTION_GROUP, mixins: [normalizeSlotMixin, formOptionsMixin], props: props$17, render: function render(h) { var label = this.label; var $options = this.formOptions.map(function (option, index) { var value = option.value, text = option.text, html = option.html, disabled = option.disabled; return h(BFormSelectOption, { attrs: { value: value, disabled: disabled }, domProps: htmlOrText(html, text), key: "option_".concat(index) }); }); return h('optgroup', { attrs: { label: label } }, [this.normalizeSlot(SLOT_NAME_FIRST), $options, this.normalizeSlot()]); } }); var props$18 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$14), props$Q), props$R), props$S), props$T), {}, { ariaInvalid: makeProp(PROP_TYPE_BOOLEAN_STRING, false), multiple: makeProp(PROP_TYPE_BOOLEAN, false), // Browsers default size to `0`, which shows 4 rows in most browsers in multiple mode // Size of `1` can bork out Firefox selectSize: makeProp(PROP_TYPE_NUMBER, 0) })), NAME_FORM_SELECT); // --- Main component --- // @vue/component var BFormSelect = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_SELECT, mixins: [idMixin, mixin, formControlMixin, formSizeMixin, formStateMixin, formCustomMixin, optionsMixin, normalizeSlotMixin], props: props$18, data: function data() { return { localValue: this[prop] }; }, 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]; } }, watch: { value: function value(newValue) { this.localValue = newValue; }, localValue: function localValue() { this.$emit(event, this.localValue); } }, methods: { focus: function focus() { attemptFocus(this.$refs.input); }, blur: function blur() { attemptBlur(this.$refs.input); }, onChange: function onChange(event) { var _this = this; var target = event.target; var selectedValue = from(target.options).filter(function (o) { return o.selected; }).map(function (o) { return '_value' in o ? o._value : o.value; }); this.localValue = target.multiple ? selectedValue : selectedValue[0]; this.$nextTick(function () { _this.$emit(EVENT_NAME_CHANGE, _this.localValue); }); } }, render: function render(h) { var name = this.name, disabled = this.disabled, required = this.required, size = this.computedSelectSize, value = this.localValue; var $options = this.formOptions.map(function (option, index) { var value = option.value, label = option.label, options = option.options, disabled = option.disabled; var key = "option_".concat(index); return isArray(options) ? h(BFormSelectOptionGroup, { props: { label: label, options: options }, key: key }) : h(BFormSelectOption, { props: { value: value, disabled: disabled }, domProps: htmlOrText(option.html, option.text), key: key }); }); return h('select', { class: this.inputClass, attrs: { id: this.safeId(), name: name, form: this.form || null, multiple: this.multiple || null, size: size, disabled: disabled, required: required, 'aria-required': required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid }, on: { change: this.onChange }, directives: [{ name: 'model', value: value }], ref: 'input' }, [this.normalizeSlot(SLOT_NAME_FIRST), $options, this.normalizeSlot()]); } }); var FormSelectPlugin = /*#__PURE__*/pluginFactory({ components: { BFormSelect: BFormSelect, BFormSelectOption: BFormSelectOption, BFormSelectOptionGroup: BFormSelectOptionGroup, BSelect: BFormSelect, BSelectOption: BFormSelectOption, BSelectOptionGroup: BFormSelectOptionGroup } }); var _watch$a; var _makeModelMixin$b = makeModelMixin('value', { // Should this really be String, to match native number inputs? type: PROP_TYPE_BOOLEAN_NUMBER }), modelMixin$a = _makeModelMixin$b.mixin, modelProps$a = _makeModelMixin$b.props, MODEL_PROP_NAME$a = _makeModelMixin$b.prop, MODEL_EVENT_NAME$a = _makeModelMixin$b.event; // 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; var KEY_CODES = [CODE_UP, CODE_DOWN, CODE_HOME, CODE_END, CODE_PAGEUP, CODE_PAGEDOWN]; // --- Props --- var props$19 = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$a), omit(props$Q, ['required', 'autofocus'])), props$S), props$T), {}, { ariaControls: makeProp(PROP_TYPE_STRING), ariaLabel: makeProp(PROP_TYPE_STRING), formatterFn: makeProp(PROP_TYPE_FUNCTION), inline: makeProp(PROP_TYPE_BOOLEAN, false), labelDecrement: makeProp(PROP_TYPE_STRING, 'Decrement'), labelIncrement: makeProp(PROP_TYPE_STRING, 'Increment'), locale: makeProp(PROP_TYPE_ARRAY_STRING), max: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_MAX), min: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_MIN), placeholder: makeProp(PROP_TYPE_STRING), readonly: makeProp(PROP_TYPE_BOOLEAN, false), repeatDelay: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_REPEAT_DELAY), repeatInterval: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_REPEAT_INTERVAL), repeatStepMultiplier: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_REPEAT_MULTIPLIER), repeatThreshold: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_REPEAT_THRESHOLD), step: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_STEP), vertical: makeProp(PROP_TYPE_BOOLEAN, false), wrap: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_FORM_SPINBUTTON); // --- Main Component --- // @vue/component var BFormSpinbutton = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_SPINBUTTON, // Mixin order is important! mixins: [attrsMixin, idMixin, modelMixin$a, formSizeMixin, formStateMixin, normalizeSlotMixin], inheritAttrs: false, props: props$19, data: function data() { return { localValue: toFloat(this[MODEL_PROP_NAME$a], null), hasFocus: false }; }, computed: { spinId: function spinId() { return this.safeId(); }, computedInline: function computedInline() { return this.inline && !this.vertical; }, computedReadonly: function computedReadonly() { return this.readonly && !this.disabled; }, computedRequired: function computedRequired() { return this.required && !this.computedReadonly && !this.disabled; }, computedStep: function computedStep() { return toFloat(this.step, DEFAULT_STEP); }, computedMin: function computedMin() { return toFloat(this.min, DEFAULT_MIN); }, computedMax: function computedMax() { // We round down to the nearest maximum step value var max = toFloat(this.max, DEFAULT_MAX); var step = this.computedStep; var min = this.computedMin; return mathFloor((max - min) / step) * step + min; }, computedDelay: function computedDelay() { var delay = toInteger(this.repeatDelay, 0); return delay > 0 ? delay : DEFAULT_REPEAT_DELAY; }, computedInterval: function computedInterval() { var interval = toInteger(this.repeatInterval, 0); return interval > 0 ? interval : DEFAULT_REPEAT_INTERVAL; }, computedThreshold: function computedThreshold() { return mathMax(toInteger(this.repeatThreshold, DEFAULT_REPEAT_THRESHOLD), 1); }, computedStepMultiplier: function computedStepMultiplier() { return mathMax(toInteger(this.repeatStepMultiplier, DEFAULT_REPEAT_MULTIPLIER), 1); }, computedPrecision: function computedPrecision() { // Quick and dirty way to get the number of decimals var step = this.computedStep; return mathFloor(step) === step ? 0 : (step.toString().split('.')[1] || '').length; }, computedMultiplier: function computedMultiplier() { return mathPow(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; }, computedFormatter: function computedFormatter() { var formatterFn = this.formatterFn; return hasPropFunction(formatterFn) ? formatterFn : this.defaultFormatter; }, computedAttrs: function computedAttrs() { return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { role: 'group', lang: this.computedLocale, tabindex: this.disabled ? null : '-1', title: this.ariaLabel }); }, computedSpinAttrs: function computedSpinAttrs() { var spinId = this.spinId, value = this.localValue, required = this.computedRequired, disabled = this.disabled, state = this.state, computedFormatter = this.computedFormatter; var hasValue = !isNull(value); return _objectSpread2(_objectSpread2({ dir: this.computedRTL ? 'rtl' : 'ltr' }, this.bvAttrs), {}, { id: spinId, role: 'spinbutton', tabindex: disabled ? 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 && required ? 'true' : null, 'aria-required': required ? '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 ? computedFormatter(value) : null }); } }, watch: (_watch$a = {}, _defineProperty(_watch$a, MODEL_PROP_NAME$a, function (value) { this.localValue = toFloat(value, null); }), _defineProperty(_watch$a, "localValue", function localValue(value) { this.$emit(MODEL_EVENT_NAME$a, value); }), _defineProperty(_watch$a, "disabled", function disabled(_disabled) { if (_disabled) { this.clearRepeat(); } }), _defineProperty(_watch$a, "readonly", function readonly(_readonly) { if (_readonly) { this.clearRepeat(); } }), _watch$a), created: function created() { // Create non reactive properties this.$_autoDelayTimer = null; this.$_autoRepeatTimer = null; this.$_keyIsDown = false; }, beforeDestroy: function beforeDestroy() { this.clearRepeat(); }, /* istanbul ignore next */ deactivated: function deactivated() { this.clearRepeat(); }, methods: { // --- Public methods --- focus: function focus() { if (!this.disabled) { attemptFocus(this.$refs.spinner); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$refs.spinner); } }, // --- Private methods --- emitChange: function emitChange() { this.$emit(EVENT_NAME_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 = mathRound((value - min) / step) * step + min + step; // We ensure that precision is maintained (decimals) value = mathRound(value * multiplier) / multiplier; // Handle if wrapping is enabled this.localValue = value > max ? wrap ? min : max : value < min ? wrap ? max : min : value; } }, onFocusBlur: function onFocusBlur(event) { if (!this.disabled) { this.hasFocus = event.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(event) { var keyCode = event.keyCode, altKey = event.altKey, ctrlKey = event.ctrlKey, metaKey = event.metaKey; /* istanbul ignore if */ if (this.disabled || this.readonly || altKey || ctrlKey || metaKey) { return; } if (arrayIncludes(KEY_CODES, keyCode)) { // https://w3c.github.io/aria-practices/#spinbutton stopEvent(event, { propagation: false }); /* istanbul ignore if */ if (this.$_keyIsDown) { // Keypress is already in progress return; } this.resetTimers(); if (arrayIncludes([CODE_UP, CODE_DOWN], keyCode)) { // The following use the custom auto-repeat handling this.$_keyIsDown = true; if (keyCode === CODE_UP) { this.handleStepRepeat(event, this.stepUp); } else if (keyCode === CODE_DOWN) { this.handleStepRepeat(event, this.stepDown); } } else { // These use native OS key repeating if (keyCode === CODE_PAGEUP) { this.stepUp(this.computedStepMultiplier); } else if (keyCode === CODE_PAGEDOWN) { this.stepDown(this.computedStepMultiplier); } else if (keyCode === CODE_HOME) { this.localValue = this.computedMin; } else if (keyCode === CODE_END) { this.localValue = this.computedMax; } } } }, onKeyup: function onKeyup(event) { // Emit a change event when the keyup happens var keyCode = event.keyCode, altKey = event.altKey, ctrlKey = event.ctrlKey, metaKey = event.metaKey; /* istanbul ignore if */ if (this.disabled || this.readonly || altKey || ctrlKey || metaKey) { return; } if (arrayIncludes(KEY_CODES, keyCode)) { stopEvent(event, { propagation: false }); this.resetTimers(); this.$_keyIsDown = false; this.emitChange(); } }, handleStepRepeat: function handleStepRepeat(event, stepper) { var _this = this; var _ref = event || {}, 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(event) { // `<body>` listener, only enabled when mousedown starts var _ref2 = event || {}, type = _ref2.type, button = _ref2.button; /* istanbul ignore if */ if (type === 'mouseup' && button) { // Ignore non left button (main === 0) mouse button click return; } stopEvent(event, { propagation: false }); 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 (_unused) {} }, resetTimers: function resetTimers() { clearTimeout(this.$_autoDelayTimer); clearInterval(this.$_autoRepeatTimer); this.$_autoDelayTimer = null; this.$_autoRepeatTimer = null; }, clearRepeat: function clearRepeat() { this.resetTimers(); this.setMouseup(false); this.$_keyIsDown = false; } }, render: function render(h) { var _this2 = this; var spinId = this.spinId, value = this.localValue, inline = this.computedInline, readonly = this.computedReadonly, vertical = this.vertical, disabled = this.disabled, computedFormatter = this.computedFormatter; var hasValue = !isNull(value); var makeButton = function makeButton(stepper, label, IconCmp, keyRef, shortcut, btnDisabled, slotName) { var $icon = h(IconCmp, { props: { scale: _this2.hasFocus ? 1.5 : 1.25 }, attrs: { 'aria-hidden': 'true' } }); var scope = { hasFocus: _this2.hasFocus }; var handler = function handler(event) { if (!disabled && !readonly) { stopEvent(event, { propagation: false }); _this2.setMouseup(true); // Since we `preventDefault()`, we must manually focus the button attemptFocus(event.currentTarget); _this2.handleStepRepeat(event, stepper); } }; return h('button', { staticClass: 'btn btn-sm border-0 rounded-0', class: { 'py-0': !vertical }, attrs: { tabindex: '-1', type: 'button', disabled: disabled || readonly || btnDisabled, 'aria-disabled': disabled || readonly || btnDisabled ? 'true' : null, 'aria-controls': spinId, 'aria-label': label || null, 'aria-keyshortcuts': shortcut || null }, on: { mousedown: handler, touchstart: handler }, key: keyRef || null, ref: keyRef }, [_this2.normalizeSlot(slotName, scope) || $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', false, SLOT_NAME_INCREMENT); var $decrement = makeButton(this.stepDown, this.labelDecrement, BIconDash, 'dec', 'ArrowDown', false, SLOT_NAME_DECREMENT); var $hidden = h(); if (this.name && !disabled) { $hidden = h('input', { 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 }, key: 'hidden' }); } var $spin = h( // We use 'output' element to make this accept a `<label for="id">` (Except IE) 'output', { staticClass: 'flex-grow-1', class: { 'd-flex': vertical, 'align-self-center': !vertical, 'align-items-center': vertical, 'border-top': vertical, 'border-bottom': vertical, 'border-left': !vertical, 'border-right': !vertical }, attrs: this.computedSpinAttrs, key: 'output', ref: 'spinner' }, [h('bdi', hasValue ? computedFormatter(value) : this.placeholder || '')]); return h('div', { staticClass: 'b-form-spinbutton form-control', class: [{ disabled: disabled, readonly: readonly, focus: this.hasFocus, 'd-inline-flex': inline || vertical, 'd-flex': !inline && !vertical, 'align-items-stretch': !vertical, 'flex-column': vertical }, this.sizeFormClass, this.stateClass], attrs: this.computedAttrs, 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 } }, vertical ? [$increment, $hidden, $spin, $decrement] : [$decrement, $hidden, $spin, $increment]); } }); var FormSpinbuttonPlugin = /*#__PURE__*/pluginFactory({ components: { BFormSpinbutton: BFormSpinbutton, BSpinbutton: BFormSpinbutton } }); var props$1a = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$g), {}, { disabled: makeProp(PROP_TYPE_BOOLEAN, false), noRemove: makeProp(PROP_TYPE_BOOLEAN, false), pill: makeProp(PROP_TYPE_BOOLEAN, false), removeLabel: makeProp(PROP_TYPE_STRING, 'Remove tag'), tag: makeProp(PROP_TYPE_STRING, 'span'), title: makeProp(PROP_TYPE_STRING), variant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_FORM_TAG); // --- Main component --- // @vue/component var BFormTag = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_TAG, mixins: [idMixin, normalizeSlotMixin], props: props$1a, methods: { onRemove: function onRemove(event) { var type = event.type, keyCode = event.keyCode; if (!this.disabled && (type === 'click' || type === 'keydown' && keyCode === CODE_DELETE)) { this.$emit(EVENT_NAME_REMOVE); } } }, render: function render(h) { var title = this.title, tag = this.tag, variant = this.variant, pill = this.pill, disabled = this.disabled; var tagId = this.safeId(); var tagLabelId = this.safeId('_taglabel_'); var $remove = h(); if (!this.noRemove && !disabled) { $remove = h(BButtonClose, { staticClass: 'b-form-tag-remove', props: { ariaLabel: this.removeLabel }, attrs: { 'aria-controls': tagId, 'aria-describedby': tagLabelId, 'aria-keyshortcuts': 'Delete' }, on: { click: this.onRemove, keydown: this.onRemove } }); } var $tag = h('span', { staticClass: 'b-form-tag-content flex-grow-1 text-truncate', attrs: { id: tagLabelId } }, this.normalizeSlot() || title); return h(BBadge, { staticClass: 'b-form-tag d-inline-flex align-items-baseline mw-100', class: { disabled: disabled }, props: { tag: tag, variant: variant, pill: pill }, attrs: { id: tagId, title: title || null, 'aria-labelledby': tagLabelId } }, [$tag, $remove]); } }); var _watch$b; var _makeModelMixin$c = makeModelMixin('value', { type: PROP_TYPE_ARRAY, defaultValue: [] }), modelMixin$b = _makeModelMixin$c.mixin, modelProps$b = _makeModelMixin$c.props, MODEL_PROP_NAME$b = _makeModelMixin$c.prop, MODEL_EVENT_NAME$b = _makeModelMixin$c.event; // Supported input types (for built in input) var TYPES$2 = ['text', 'email', 'tel', 'url', 'number']; // Default ignore input focus selector var DEFAULT_INPUT_FOCUS_SELECTOR = ['.b-form-tag', 'button', 'input', 'select'].join(' '); // --- Helper 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(event) { return isString(event) ? event : isEvent(event) ? event.target.value || '' : ''; }; // Returns a fresh empty `tagsState` object var cleanTagsState = function cleanTagsState() { return { all: [], valid: [], invalid: [], duplicate: [] }; }; // --- Props --- var props$1b = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$b), props$Q), props$S), props$T), {}, { addButtonText: makeProp(PROP_TYPE_STRING, 'Add'), addButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-secondary'), // Enable change event triggering tag addition // Handy if using <select> as the input addOnChange: makeProp(PROP_TYPE_BOOLEAN, false), duplicateTagText: makeProp(PROP_TYPE_STRING, 'Duplicate tag(s)'), // Disable the input focus behavior when clicking // on element matching the selector (or selectors) ignoreInputFocusSelector: makeProp(PROP_TYPE_ARRAY_STRING, DEFAULT_INPUT_FOCUS_SELECTOR), // Additional attributes to add to the input element inputAttrs: makeProp(PROP_TYPE_OBJECT, {}), inputClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), inputId: makeProp(PROP_TYPE_STRING), inputType: makeProp(PROP_TYPE_STRING, 'text', function (value) { return arrayIncludes(TYPES$2, value); }), invalidTagText: makeProp(PROP_TYPE_STRING, 'Invalid tag(s)'), limit: makeProp(PROP_TYPE_NUMBER), limitTagsText: makeProp(PROP_TYPE_STRING, 'Tag limit reached'), // Disable ENTER key from triggering tag addition noAddOnEnter: makeProp(PROP_TYPE_BOOLEAN, false), // Disable the focus ring on the root element noOuterFocus: makeProp(PROP_TYPE_BOOLEAN, false), noTagRemove: makeProp(PROP_TYPE_BOOLEAN, false), placeholder: makeProp(PROP_TYPE_STRING, 'Add tag...'), // Enable deleting last tag in list when CODE_BACKSPACE is // pressed and input is empty removeOnDelete: makeProp(PROP_TYPE_BOOLEAN, false), // Character (or characters) that trigger adding tags separator: makeProp(PROP_TYPE_ARRAY_STRING), tagClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), tagPills: makeProp(PROP_TYPE_BOOLEAN, false), tagRemoveLabel: makeProp(PROP_TYPE_STRING, 'Remove tag'), tagRemovedLabel: makeProp(PROP_TYPE_STRING, 'Tag removed'), tagValidator: makeProp(PROP_TYPE_FUNCTION), tagVariant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_FORM_TAGS); // --- Main component --- // @vue/component var BFormTags = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_TAGS, mixins: [idMixin, modelMixin$b, formControlMixin, formSizeMixin, formStateMixin, normalizeSlotMixin], props: props$1b, 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$2, this.inputType) ? this.inputType : 'text'; }, computedInputAttrs: function computedInputAttrs() { var disabled = this.disabled, form = this.form; return _objectSpread2(_objectSpread2({}, this.inputAttrs), {}, { // Must have attributes id: this.computedInputId, value: this.newTag, disabled: disabled, form: form }); }, computedInputHandlers: function computedInputHandlers() { return { input: this.onInputInput, change: this.onInputChange, keydown: this.onInputKeydown, reset: this.reset }; }, 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; }, computeIgnoreInputFocusSelector: function computeIgnoreInputFocusSelector() { // Normalize to an single selector with selectors separated by `,` return concat(this.ignoreInputFocusSelector).filter(identity).join(',').trim(); }, 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; }, isLimitReached: function isLimitReached() { var limit = this.limit; return isNumber(limit) && limit >= 0 && this.tags.length >= limit; } }, watch: (_watch$b = {}, _defineProperty(_watch$b, MODEL_PROP_NAME$b, function (newValue) { this.tags = cleanTags(newValue); }), _defineProperty(_watch$b, "tags", function tags(newValue, oldValue) { // Update the `v-model` (if it differs from the value prop) if (!looseEqual(newValue, this[MODEL_PROP_NAME$b])) { this.$emit(MODEL_EVENT_NAME$b, newValue); } if (!looseEqual(newValue, oldValue)) { newValue = concat(newValue).filter(identity); oldValue = concat(oldValue).filter(identity); this.removedTags = oldValue.filter(function (old) { return !arrayIncludes(newValue, old); }); } }), _defineProperty(_watch$b, "tagsState", function tagsState(newValue, oldValue) { // Emit a tag-state event when the `tagsState` object changes if (!looseEqual(newValue, oldValue)) { this.$emit(EVENT_NAME_TAG_STATE, newValue.valid, newValue.invalid, newValue.duplicate); } }), _watch$b), 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[MODEL_PROP_NAME$b]); }, mounted: function mounted() { var _this2 = this; // Listen for form reset events, to reset the tags input var $form = closest('form', this.$el); if ($form) { eventOn($form, 'reset', this.reset, EVENT_OPTIONS_PASSIVE); this.$on(HOOK_EVENT_NAME_BEFORE_DESTROY, function () { eventOff($form, 'reset', _this2.reset, EVENT_OPTIONS_PASSIVE); }); } }, methods: { addTag: function addTag(newTag) { newTag = isString(newTag) ? newTag : this.newTag; /* istanbul ignore next */ if (this.disabled || trim(newTag) === '' || this.isLimitReached) { // 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 _this3 = 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 () { _this3.focus(); }); }, reset: function reset() { var _this4 = this; this.newTag = ''; this.tags = []; this.$nextTick(function () { _this4.removedTags = []; _this4.tagsState = cleanTagsState(); }); }, // --- Input element event handlers --- onInputInput: function onInputInput(event) { /* istanbul ignore next: hard to test composition events */ if (this.disabled || isEvent(event) && event.target.composing) { // `event.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(event); 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(event) { // Change is triggered on `<input>` blur, or `<select>` selected // This event is opt-in if (!this.disabled && this.addOnChange) { var newTag = processEventValue(event); /* istanbul ignore next */ if (this.newTag !== newTag) { this.newTag = newTag; } this.addTag(); } }, onInputKeydown: function onInputKeydown(event) { // Early exit /* istanbul ignore next */ if (this.disabled || !isEvent(event)) { return; } var keyCode = event.keyCode; var value = event.target.value || ''; /* istanbul ignore else: testing to be added later */ if (!this.noAddOnEnter && keyCode === CODE_ENTER) { // Attempt to add the tag when user presses enter stopEvent(event, { propagation: false }); this.addTag(); } else if (this.removeOnDelete && (keyCode === CODE_BACKSPACE || keyCode === CODE_DELETE) && value === '') { // Remove the last tag if the user pressed backspace/delete and the input is empty stopEvent(event, { propagation: false }); this.tags = this.tags.slice(0, -1); } }, // --- Wrapper event handlers --- onClick: function onClick(event) { var _this5 = this; var ignoreFocusSelector = this.computeIgnoreInputFocusSelector; var target = event.target; if (!this.disabled && !isActiveElement(target) && (!ignoreFocusSelector || !closest(ignoreFocusSelector, target, true))) { this.$nextTick(function () { _this5.focus(); }); } }, onFocusin: function onFocusin() { this.hasFocus = true; }, onFocusout: function onFocusout() { this.hasFocus = false; }, handleAutofocus: function handleAutofocus() { var _this6 = this; this.$nextTick(function () { requestAF(function () { if (_this6.autofocus && !_this6.disabled) { _this6.focus(); } }); }); }, // --- Public methods --- focus: function focus() { if (!this.disabled) { attemptFocus(this.getInput()); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.getInput()); } }, // --- 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 _this7 = 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(_this7.tags, tag) || arrayIncludes(parsed.valid, tag)) { // Unique duplicate tags if (!arrayIncludes(parsed.duplicate, tag)) { parsed.duplicate.push(tag); } } else if (_this7.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) { var tagValidator = this.tagValidator; return hasPropFunction(tagValidator) ? tagValidator(tag) : true; }, getInput: function getInput() { // Returns the input element reference (or null if not found) // We need to escape `computedInputId` since it can be user-provided return select("#".concat(cssEscape(this.computedInputId)), this.$el); }, // Default User Interface render defaultRender: function defaultRender(_ref) { var addButtonText = _ref.addButtonText, addButtonVariant = _ref.addButtonVariant, addTag = _ref.addTag, disableAddButton = _ref.disableAddButton, disabled = _ref.disabled, duplicateTagText = _ref.duplicateTagText, inputAttrs = _ref.inputAttrs, inputClass = _ref.inputClass, inputHandlers = _ref.inputHandlers, inputType = _ref.inputType, invalidTagText = _ref.invalidTagText, isDuplicate = _ref.isDuplicate, isInvalid = _ref.isInvalid, isLimitReached = _ref.isLimitReached, limitTagsText = _ref.limitTagsText, noTagRemove = _ref.noTagRemove, placeholder = _ref.placeholder, removeTag = _ref.removeTag, tagClass = _ref.tagClass, tagPills = _ref.tagPills, tagRemoveLabel = _ref.tagRemoveLabel, tagVariant = _ref.tagVariant, tags = _ref.tags; var h = this.$createElement; // Make the list of tags var $tags = tags.map(function (tag) { tag = toString$1(tag); return h(BFormTag, { class: tagClass, // `BFormTag` will auto generate an ID // so we do not need to set the ID prop props: { disabled: disabled, noRemove: noTagRemove, pill: tagPills, removeLabel: tagRemoveLabel, tag: 'li', title: tag, variant: tagVariant }, on: { remove: function remove() { return removeTag(tag); } }, key: "tags_".concat(tag) }, tag); }); // Feedback IDs if needed var invalidFeedbackId = invalidTagText && isInvalid ? this.safeId('__invalid_feedback__') : null; var duplicateFeedbackId = duplicateTagText && isDuplicate ? this.safeId('__duplicate_feedback__') : null; var limitFeedbackId = limitTagsText && isLimitReached ? this.safeId('__limit_feedback__') : null; // Compute the `aria-describedby` attribute value var ariaDescribedby = [inputAttrs['aria-describedby'], invalidFeedbackId, duplicateFeedbackId, limitFeedbackId].filter(identity).join(' '); // Input var $input = h('input', { 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(_objectSpread2({}, inputAttrs), {}, { 'aria-describedby': ariaDescribedby || null, type: inputType, placeholder: placeholder || null }), domProps: { value: inputAttrs.value }, on: inputHandlers, // Directive needed to get `event.target.composing` set (if needed) directives: [{ name: 'model', value: inputAttrs.value }], ref: 'input' }); // Add button var $button = h(BButton, { 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: { disabled: disableAddButton || isLimitReached, variant: addButtonVariant }, on: { click: function click() { return addTag(); } }, ref: 'button' }, [this.normalizeSlot(SLOT_NAME_ADD_BUTTON_TEXT) || addButtonText]); // ID of the tags + input `<ul>` list // Note we could concatenate `inputAttrs.id` with '__tag_list__' // but `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', { staticClass: 'b-from-tags-field flex-grow-1', attrs: { role: 'none', 'aria-live': 'off', 'aria-controls': tagListId }, key: 'tags_field' }, [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', { staticClass: 'b-form-tags-list list-unstyled mb-0 d-flex flex-wrap align-items-center', attrs: { id: tagListId }, key: 'tags_list' }, [$tags, $field]); // Assemble the feedback var $feedback = h(); if (invalidTagText || duplicateTagText || limitTagsText) { // 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, { props: { id: invalidFeedbackId, forceShow: true }, key: 'tags_invalid_feedback' }, [this.invalidTagText, ': ', this.invalidTags.join(joiner)]); } // Duplicate tag feedback if needed (warning, not error) var $duplicate = h(); if (duplicateFeedbackId) { $duplicate = h(BFormText, { props: { id: duplicateFeedbackId }, key: 'tags_duplicate_feedback' }, [this.duplicateTagText, ': ', this.duplicateTags.join(joiner)]); } // Limit tags feedback if needed (warning, not error) var $limit = h(); if (limitFeedbackId) { $limit = h(BFormText, { props: { id: limitFeedbackId }, key: 'tags_limit_feedback' }, [limitTagsText]); } $feedback = h('div', { attrs: { 'aria-live': 'polite', 'aria-atomic': 'true' }, key: 'tags_feedback' }, [$invalid, $duplicate, $limit]); } // Return the content return [$ul, $feedback]; } }, render: function render(h) { var name = this.name, disabled = this.disabled, required = this.required, form = this.form, tags = this.tags, computedInputId = this.computedInputId, hasFocus = this.hasFocus, noOuterFocus = this.noOuterFocus; // Scoped slot properties var scope = _objectSpread2({ // Array of tags (shallow copy to prevent mutations) tags: tags.slice(), // <input> v-bind:inputAttrs inputAttrs: this.computedInputAttrs, // We don't include this in the attrs, as users may want to override this inputType: this.computedInputType, // <input> v-on:inputHandlers inputHandlers: this.computedInputHandlers, // Methods removeTag: this.removeTag, addTag: this.addTag, reset: this.reset, // <input> :id="inputId" inputId: computedInputId, // Invalid/Duplicate state information isInvalid: this.hasInvalidTags, invalidTags: this.invalidTags.slice(), isDuplicate: this.hasDuplicateTags, duplicateTags: this.duplicateTags.slice(), isLimitReached: this.isLimitReached, // If the 'Add' button should be disabled disableAddButton: this.disableAddButton }, pick(this.$props, ['addButtonText', 'addButtonVariant', 'disabled', 'duplicateTagText', 'form', 'inputClass', 'invalidTagText', 'limit', 'limitTagsText', 'noTagRemove', 'placeholder', 'required', 'separator', 'size', 'state', 'tagClass', 'tagPills', 'tagRemoveLabel', 'tagVariant'])); // Generate the user interface var $content = this.normalizeSlot(SLOT_NAME_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: computedInputId, 'aria-live': 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': 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 (name && !disabled) { // We add hidden inputs for each tag if a name is provided // When there are currently no tags, a visually hidden input // with empty value is rendered for proper required handling var hasTags = tags.length > 0; $hidden = (hasTags ? tags : ['']).map(function (tag) { return h('input', { class: { 'sr-only': !hasTags }, attrs: { type: hasTags ? 'hidden' : 'text', value: tag, required: required, name: name, form: form }, key: "tag_input_".concat(tag) }); }); } // Return the rendered output return h('div', { staticClass: 'b-form-tags form-control h-auto', class: [{ focus: hasFocus && !noOuterFocus && !disabled, disabled: disabled }, this.sizeFormClass, this.stateClass], attrs: { id: this.safeId(), role: 'group', tabindex: disabled || noOuterFocus ? null : '-1', 'aria-describedby': this.safeId('__selected_tags__') }, on: { click: this.onClick, focusin: this.onFocusin, focusout: this.onFocusout } }, [$output, $removed, $content, $hidden]); } }); var FormTagsPlugin = /*#__PURE__*/pluginFactory({ components: { BFormTags: BFormTags, BTags: BFormTags, BFormTag: BFormTag, BTag: BFormTag } }); var props$1c = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$Q), props$S), props$T), props$10), {}, { maxRows: makeProp(PROP_TYPE_NUMBER_STRING), // When in auto resize mode, disable shrinking to content height noAutoShrink: makeProp(PROP_TYPE_BOOLEAN, false), // Disable the resize handle of textarea noResize: makeProp(PROP_TYPE_BOOLEAN, false), rows: makeProp(PROP_TYPE_NUMBER_STRING, 2), // 'soft', 'hard' or 'off' // Browser default is 'soft' wrap: makeProp(PROP_TYPE_STRING, 'soft') })), NAME_FORM_TEXTAREA); // --- Main component --- // @vue/component var BFormTextarea = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_TEXTAREA, directives: { 'b-visible': VBVisible }, // Mixin order is important! mixins: [listenersMixin, idMixin, listenOnRootMixin, formControlMixin, formSizeMixin, formStateMixin, formTextMixin, formSelectionMixin, formValidityMixin], props: props$1c, 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 mathMax(toInteger(this.rows, 2), 2); }, computedMaxRows: function computedMaxRows() { return mathMax(this.computedMinRows, toInteger(this.maxRows, 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; }, computedAttrs: function computedAttrs() { var disabled = this.disabled, required = this.required; return { id: this.safeId(), name: this.name || null, form: this.form || null, disabled: disabled, placeholder: this.placeholder || null, required: required, autocomplete: this.autocomplete || null, readonly: this.readonly || this.plaintext, rows: this.computedRows, wrap: this.wrap || null, 'aria-required': this.required ? 'true' : null, 'aria-invalid': this.computedAriaInvalid }; }, computedListeners: function computedListeners() { return _objectSpread2(_objectSpread2({}, this.bvListeners), {}, { input: this.onInput, change: this.onChange, blur: this.onBlur }); } }, watch: { localValue: function localValue() { this.setHeight(); } }, mounted: function mounted() { this.setHeight(); }, methods: { // Called by intersection observer directive /* istanbul ignore next */ visibleCallback: function visibleCallback(visible) { 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(); }); }); }, /* istanbul ignore next: can't test getComputedStyle in JSDOM */ computeHeight: function computeHeight() { 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 = toFloat(computedStyle.lineHeight, 1); // Calculate height of border and padding var border = toFloat(computedStyle.borderTopWidth, 0) + toFloat(computedStyle.borderBottomWidth, 0); var padding = toFloat(computedStyle.paddingTop, 0) + toFloat(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 = getStyle(el, 'height') || computedStyle.height; // Probe scrollHeight by temporarily changing the height to `auto` setStyle(el, '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 setStyle(el, 'height', oldHeight); // Calculate content height in 'rows' (scrollHeight includes padding but not border) var contentRows = mathMax((scrollHeight - padding) / lineHeight, 2); // Calculate number of rows to display (limited within min/max rows) var rows = mathMin(mathMax(contentRows, this.computedMinRows), this.computedMaxRows); // Calculate the required height of the textarea including border and padding (in pixels) var height = mathMax(mathCeil(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 && toFloat(oldHeight, 0) > height) { return oldHeight; } // Return the new computed CSS height in px units return "".concat(height, "px"); } }, render: function render(h) { return h('textarea', { class: this.computedClass, style: this.computedStyle, directives: [{ name: 'b-visible', value: this.visibleCallback, // If textarea is within 640px of viewport, consider it visible modifiers: { '640': true } }], attrs: this.computedAttrs, domProps: { value: this.localValue }, on: this.computedListeners, ref: 'input' }); } }); var FormTextareaPlugin = /*#__PURE__*/pluginFactory({ components: { BFormTextarea: BFormTextarea, BTextarea: BFormTextarea } }); var _watch$c; var _makeModelMixin$d = makeModelMixin('value', { type: PROP_TYPE_STRING, defaultValue: '' }), modelMixin$c = _makeModelMixin$d.mixin, modelProps$c = _makeModelMixin$d.props, MODEL_PROP_NAME$c = _makeModelMixin$d.prop, MODEL_EVENT_NAME$c = _makeModelMixin$d.event; var NUMERIC = 'numeric'; // --- Helper methods --- var padLeftZeros = function padLeftZeros(value) { return "00".concat(value || '').slice(-2); }; var parseHMS = function parseHMS(value) { value = toString$1(value); var hh = null, mm = null, ss = null; if (RX_TIME.test(value)) { var _value$split$map = value.split(':').map(function (v) { return toInteger(v, null); }); var _value$split$map2 = _slicedToArray(_value$split$map, 3); hh = _value$split$map2[0]; mm = _value$split$map2[1]; ss = _value$split$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(':'); }; // --- Props --- var props$1d = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$c), pick(props$19, ['labelIncrement', 'labelDecrement'])), {}, { // ID of label element ariaLabelledby: makeProp(PROP_TYPE_STRING), disabled: makeProp(PROP_TYPE_BOOLEAN, false), hidden: makeProp(PROP_TYPE_BOOLEAN, false), hideHeader: makeProp(PROP_TYPE_BOOLEAN, false), // 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 hour12: makeProp(PROP_TYPE_BOOLEAN, null), labelAm: makeProp(PROP_TYPE_STRING, 'AM'), labelAmpm: makeProp(PROP_TYPE_STRING, 'AM/PM'), labelHours: makeProp(PROP_TYPE_STRING, 'Hours'), labelMinutes: makeProp(PROP_TYPE_STRING, 'Minutes'), labelNoTimeSelected: makeProp(PROP_TYPE_STRING, 'No time selected'), labelPm: makeProp(PROP_TYPE_STRING, 'PM'), labelSeconds: makeProp(PROP_TYPE_STRING, 'Seconds'), labelSelected: makeProp(PROP_TYPE_STRING, 'Selected time'), locale: makeProp(PROP_TYPE_ARRAY_STRING), minutesStep: makeProp(PROP_TYPE_NUMBER_STRING, 1), readonly: makeProp(PROP_TYPE_BOOLEAN, false), secondsStep: makeProp(PROP_TYPE_NUMBER_STRING, 1), // If `true`, show the second spinbutton showSeconds: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_TIME); // --- Main component --- // @vue/component var BTime = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TIME, mixins: [idMixin, modelMixin$c, normalizeSlotMixin], props: props$1d, data: function data() { var parsed = parseHMS(this[MODEL_PROP_NAME$c] || ''); 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 || ' '; }, spinScopedSlots: function spinScopedSlots() { var h = this.$createElement; return { increment: function increment(_ref2) { var hasFocus = _ref2.hasFocus; return h(BIconChevronUp, { props: { scale: hasFocus ? 1.5 : 1.25 }, attrs: { 'aria-hidden': 'true' } }); }, decrement: function decrement(_ref3) { var hasFocus = _ref3.hasFocus; return h(BIconChevronUp, { props: { flipV: true, scale: hasFocus ? 1.5 : 1.25 }, attrs: { 'aria-hidden': 'true' } }); } }; } }, watch: (_watch$c = {}, _defineProperty(_watch$c, MODEL_PROP_NAME$c, function (newValue, oldValue) { if (newValue !== oldValue && !looseEqual(parseHMS(newValue), parseHMS(this.computedHMS))) { var _parseHMS = parseHMS(newValue), hours = _parseHMS.hours, minutes = _parseHMS.minutes, seconds = _parseHMS.seconds, ampm = _parseHMS.ampm; this.modelHours = hours; this.modelMinutes = minutes; this.modelSeconds = seconds; this.modelAmpm = ampm; } }), _defineProperty(_watch$c, "computedHMS", function computedHMS(newValue, oldValue) { if (newValue !== oldValue) { this.$emit(MODEL_EVENT_NAME$c, newValue); } }), _defineProperty(_watch$c, "context", function context(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(EVENT_NAME_CONTEXT, newValue); } }), _defineProperty(_watch$c, "modelAmpm", function modelAmpm(newValue, oldValue) { var _this = this; if (newValue !== oldValue) { var hours = isNull(this.modelHours) ? 0 : this.modelHours; this.$nextTick(function () { if (newValue === 0 && hours > 11) { // Switched to AM _this.modelHours = hours - 12; } else if (newValue === 1 && hours < 12) { // Switched to PM _this.modelHours = hours + 12; } }); } }), _defineProperty(_watch$c, "modelHours", function modelHours(newHours, oldHours) { if (newHours !== oldHours) { this.modelAmpm = newHours > 11 ? 1 : 0; } }), _watch$c), created: function created() { var _this2 = this; this.$nextTick(function () { _this2.$emit(EVENT_NAME_CONTEXT, _this2.context); }); }, mounted: function mounted() { this.setLive(true); }, /* istanbul ignore next */ activated: function activated() { this.setLive(true); }, /* istanbul ignore next */ deactivated: function deactivated() { this.setLive(false); }, beforeDestroy: function beforeDestroy() { this.setLive(false); }, methods: { // Public methods focus: function focus() { if (!this.disabled) { // We focus the first spin button attemptFocus(this.$refs.spinners[0]); } }, blur: function blur() { if (!this.disabled) { var activeElement = getActiveElement(); if (contains(this.$el, activeElement)) { attemptBlur(activeElement); } } }, // 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' ? /* istanbul ignore next */ 24 : hh === 12 && hourCycle === 'h11' ? /* istanbul ignore next */ 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 event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = event.type, keyCode = event.keyCode; if (!this.disabled && type === 'keydown' && (keyCode === CODE_LEFT || keyCode === CODE_RIGHT)) { stopEvent(event); var spinners = this.$refs.spinners || []; var index = spinners.map(function (cmp) { return !!cmp.hasFocus; }).indexOf(true); index = index + (keyCode === CODE_LEFT ? -1 : 1); index = index >= spinners.length ? 0 : index < 0 ? spinners.length - 1 : index; attemptFocus(spinners[index]); } }, 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, { 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), scopedSlots: _this4.spinScopedSlots, 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 }, key: key, ref: 'spinners', refInFor: true }); }; // 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', 'b-time-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', 'b-time-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', 'b-time-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', 'b-time-ampm', { 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: /* istanbul ignore next */ function click(event) { if (event.target === event.currentTarget) { _this4.focus(); } } } }, $spinners); // Selected type display var $value = h('output', { staticClass: 'form-control form-control-sm 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', { staticClass: 'b-time-header', class: { 'sr-only': this.hideHeader } }, [$value]); // Optional bottom slot var $slot = this.normalizeSlot(); $slot = $slot ? h('footer', { staticClass: 'b-time-footer' }, $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 _watch$d; var _makeModelMixin$e = makeModelMixin('value', { type: PROP_TYPE_STRING, defaultValue: '' }), modelMixin$d = _makeModelMixin$e.mixin, modelProps$d = _makeModelMixin$e.props, MODEL_PROP_NAME$d = _makeModelMixin$e.prop, MODEL_EVENT_NAME$d = _makeModelMixin$e.event; // --- Props --- var timeProps = omit(props$1d, ['hidden', 'id', 'value']); var formBtnLabelControlProps$1 = omit(props$Z, ['formattedValue', 'id', 'lang', 'rtl', 'value']); var props$1e = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$d), timeProps), formBtnLabelControlProps$1), {}, { closeButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-secondary'), labelCloseButton: makeProp(PROP_TYPE_STRING, 'Close'), labelNowButton: makeProp(PROP_TYPE_STRING, 'Select now'), labelResetButton: makeProp(PROP_TYPE_STRING, 'Reset'), noCloseButton: makeProp(PROP_TYPE_BOOLEAN, false), nowButton: makeProp(PROP_TYPE_BOOLEAN, false), nowButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-primary'), resetButton: makeProp(PROP_TYPE_BOOLEAN, false), resetButtonVariant: makeProp(PROP_TYPE_STRING, 'outline-danger'), resetValue: makeProp(PROP_TYPE_DATE_STRING) })), NAME_FORM_TIMEPICKER); // --- Main component --- // @vue/component var BFormTimepicker = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_FORM_TIMEPICKER, mixins: [idMixin, modelMixin$d], props: props$1e, data: function data() { return { // We always use `HH:mm:ss` value internally localHMS: this[MODEL_PROP_NAME$d] || '', // 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; } }, watch: (_watch$d = {}, _defineProperty(_watch$d, MODEL_PROP_NAME$d, function (newValue) { this.localHMS = newValue || ''; }), _defineProperty(_watch$d, "localHMS", function localHMS(newValue) { // We only update the v-model value when the timepicker // is open, to prevent cursor jumps when bound to a // text input in button only mode if (this.isVisible) { this.$emit(MODEL_EVENT_NAME$d, newValue || ''); } }), _watch$d), methods: { // Public methods focus: function focus() { if (!this.disabled) { attemptFocus(this.$refs.control); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$refs.control); } }, // 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(EVENT_NAME_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 () { attemptFocus(_this2.$refs.time); _this2.$emit(EVENT_NAME_SHOWN); }); }, onHidden: function onHidden() { this.isVisible = false; this.$emit(EVENT_NAME_HIDDEN); }, // Render function helpers defaultButtonFn: function defaultButtonFn(_ref) { var isHovered = _ref.isHovered, hasFocus = _ref.hasFocus; return this.$createElement(isHovered || hasFocus ? BIconClockFill : BIconClock, { attrs: { 'aria-hidden': 'true' } }); } }, render: function render(h) { var localHMS = this.localHMS, disabled = this.disabled, readonly = this.readonly, $props = this.$props; var placeholder = isUndefinedOrNull(this.placeholder) ? this.labelNoTimeSelected : this.placeholder; // Footer buttons var $footer = []; if (this.nowButton) { var label = this.labelNowButton; $footer.push(h(BButton, { props: { size: 'sm', disabled: disabled || readonly, variant: this.nowButtonVariant }, attrs: { 'aria-label': label || null }, on: { click: this.onNowButton }, key: 'now-btn' }, label)); } if (this.resetButton) { if ($footer.length > 0) { // Add a "spacer" between buttons (' ') $footer.push(h('span', "\xA0")); } 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 }, key: 'reset-btn' }, _label)); } if (!this.noCloseButton) { // Add a "spacer" between buttons (' ') if ($footer.length > 0) { $footer.push(h('span', "\xA0")); } 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 }, key: 'close-btn' }, _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 $time = h(BTime, { staticClass: 'b-form-time-control', props: _objectSpread2(_objectSpread2({}, pluckProps(timeProps, $props)), {}, { value: localHMS, hidden: !this.isVisible }), on: { input: this.onInput, context: this.onContext }, ref: 'time' }, $footer); return h(BVFormBtnLabelControl, { staticClass: 'b-form-timepicker', props: _objectSpread2(_objectSpread2({}, pluckProps(formBtnLabelControlProps$1, $props)), {}, { id: this.safeId(), value: localHMS, formattedValue: localHMS ? this.formattedValue : '', placeholder: placeholder, rtl: this.isRTL, lang: this.computedLang }), on: { show: this.onShow, shown: this.onShown, hidden: this.onHidden }, scopedSlots: _defineProperty({}, SLOT_NAME_BUTTON_CONTENT, this.$scopedSlots[SLOT_NAME_BUTTON_CONTENT] || this.defaultButtonFn), ref: 'control' }, [$time]); } }); var FormTimepickerPlugin = /*#__PURE__*/pluginFactory({ components: { BFormTimepicker: BFormTimepicker, BTimepicker: BFormTimepicker } }); var ImagePlugin = /*#__PURE__*/pluginFactory({ components: { BImg: BImg, BImgLazy: BImgLazy } }); var props$1f = makePropsConfigurable({ tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_INPUT_GROUP_TEXT); // --- Main component --- // @vue/component var BInputGroupText = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_INPUT_GROUP_TEXT, functional: true, props: props$1f, 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 props$1g = makePropsConfigurable({ append: makeProp(PROP_TYPE_BOOLEAN, false), id: makeProp(PROP_TYPE_STRING), isText: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_INPUT_GROUP_ADDON); // --- Main component --- // @vue/component var BInputGroupAddon = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_INPUT_GROUP_ADDON, functional: true, props: props$1g, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var append = props.append; return h(props.tag, a(data, { class: { 'input-group-append': append, 'input-group-prepend': !append }, attrs: { id: props.id } }), props.isText ? [h(BInputGroupText, children)] : children); } }); var props$1h = makePropsConfigurable(omit(props$1g, ['append']), NAME_INPUT_GROUP_APPEND); // --- Main component --- // @vue/component var BInputGroupAppend = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_INPUT_GROUP_APPEND, functional: true, props: props$1h, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; // Pass all our data down to child, and set `append` to `true` return h(BInputGroupAddon, a(data, { props: _objectSpread2(_objectSpread2({}, props), {}, { append: true }) }), children); } }); var props$1i = makePropsConfigurable(omit(props$1g, ['append']), NAME_INPUT_GROUP_PREPEND); // --- Main component --- // @vue/component var BInputGroupPrepend = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_INPUT_GROUP_PREPEND, functional: true, props: props$1i, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; // Pass all our data down to child, and set `append` to `true` return h(BInputGroupAddon, a(data, { props: _objectSpread2(_objectSpread2({}, props), {}, { append: false }) }), children); } }); var props$1j = makePropsConfigurable({ append: makeProp(PROP_TYPE_STRING), appendHtml: makeProp(PROP_TYPE_STRING), id: makeProp(PROP_TYPE_STRING), prepend: makeProp(PROP_TYPE_STRING), prependHtml: makeProp(PROP_TYPE_STRING), size: makeProp(PROP_TYPE_STRING), tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_INPUT_GROUP); // --- Main component --- // @vue/component var BInputGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_INPUT_GROUP, functional: true, props: props$1j, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, slots = _ref.slots, scopedSlots = _ref.scopedSlots; var prepend = props.prepend, prependHtml = props.prependHtml, append = props.append, appendHtml = props.appendHtml, size = props.size; var $scopedSlots = scopedSlots || {}; var $slots = slots(); var slotScope = {}; var $prepend = h(); var hasPrependSlot = hasNormalizedSlot(SLOT_NAME_PREPEND, $scopedSlots, $slots); if (hasPrependSlot || prepend || prependHtml) { $prepend = h(BInputGroupPrepend, [hasPrependSlot ? normalizeSlot(SLOT_NAME_PREPEND, slotScope, $scopedSlots, $slots) : h(BInputGroupText, { domProps: htmlOrText(prependHtml, prepend) })]); } var $append = h(); var hasAppendSlot = hasNormalizedSlot(SLOT_NAME_APPEND, $scopedSlots, $slots); if (hasAppendSlot || append || appendHtml) { $append = h(BInputGroupAppend, [hasAppendSlot ? normalizeSlot(SLOT_NAME_APPEND, slotScope, $scopedSlots, $slots) : h(BInputGroupText, { domProps: htmlOrText(appendHtml, append) })]); } return h(props.tag, a(data, { staticClass: 'input-group', class: _defineProperty({}, "input-group-".concat(size), size), attrs: { id: props.id || null, role: 'group' } }), [$prepend, normalizeSlot(SLOT_NAME_DEFAULT, slotScope, $scopedSlots, $slots), $append]); } }); var InputGroupPlugin = /*#__PURE__*/pluginFactory({ components: { BInputGroup: BInputGroup, BInputGroupAddon: BInputGroupAddon, BInputGroupPrepend: BInputGroupPrepend, BInputGroupAppend: BInputGroupAppend, BInputGroupText: BInputGroupText } }); var props$1k = makePropsConfigurable({ // String breakpoint name new in Bootstrap v4.4.x fluid: makeProp(PROP_TYPE_BOOLEAN_STRING, false), tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_CONTAINER); // --- Main component --- // @vue/component var BContainer = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_CONTAINER, functional: true, props: props$1k, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var fluid = props.fluid; return h(props.tag, a(data, { class: _defineProperty({ container: !(fluid || fluid === ''), 'container-fluid': fluid === true || fluid === '' }, "container-".concat(fluid), fluid && fluid !== true) }), children); } }); var props$1l = makePropsConfigurable({ bgVariant: makeProp(PROP_TYPE_STRING), borderVariant: makeProp(PROP_TYPE_STRING), containerFluid: makeProp(PROP_TYPE_BOOLEAN_STRING, false), fluid: makeProp(PROP_TYPE_BOOLEAN, false), header: makeProp(PROP_TYPE_STRING), headerHtml: makeProp(PROP_TYPE_STRING), headerLevel: makeProp(PROP_TYPE_NUMBER_STRING, 3), headerTag: makeProp(PROP_TYPE_STRING, 'h1'), lead: makeProp(PROP_TYPE_STRING), leadHtml: makeProp(PROP_TYPE_STRING), leadTag: makeProp(PROP_TYPE_STRING, 'p'), tag: makeProp(PROP_TYPE_STRING, 'div'), textVariant: makeProp(PROP_TYPE_STRING) }, NAME_JUMBOTRON); // --- Main component --- // @vue/component var BJumbotron = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_JUMBOTRON, functional: true, props: props$1l, render: function render(h, _ref) { var _class2; var props = _ref.props, data = _ref.data, slots = _ref.slots, scopedSlots = _ref.scopedSlots; var header = props.header, headerHtml = props.headerHtml, lead = props.lead, leadHtml = props.leadHtml, textVariant = props.textVariant, bgVariant = props.bgVariant, borderVariant = props.borderVariant; var $scopedSlots = scopedSlots || {}; var $slots = slots(); var slotScope = {}; var $header = h(); var hasHeaderSlot = hasNormalizedSlot(SLOT_NAME_HEADER, $scopedSlots, $slots); if (hasHeaderSlot || header || headerHtml) { var headerLevel = props.headerLevel; $header = h(props.headerTag, { class: _defineProperty({}, "display-".concat(headerLevel), headerLevel), domProps: hasHeaderSlot ? {} : htmlOrText(headerHtml, header) }, normalizeSlot(SLOT_NAME_HEADER, slotScope, $scopedSlots, $slots)); } var $lead = h(); var hasLeadSlot = hasNormalizedSlot(SLOT_NAME_LEAD, $scopedSlots, $slots); if (hasLeadSlot || lead || leadHtml) { $lead = h(props.leadTag, { staticClass: 'lead', domProps: hasLeadSlot ? {} : htmlOrText(leadHtml, lead) }, normalizeSlot(SLOT_NAME_LEAD, slotScope, $scopedSlots, $slots)); } var $children = [$header, $lead, normalizeSlot(SLOT_NAME_DEFAULT, slotScope, $scopedSlots, $slots)]; // If fluid, wrap content in a container if (props.fluid) { $children = [h(BContainer, { props: { fluid: props.containerFluid } }, $children)]; } return h(props.tag, a(data, { staticClass: 'jumbotron', class: (_class2 = { 'jumbotron-fluid': props.fluid }, _defineProperty(_class2, "text-".concat(textVariant), textVariant), _defineProperty(_class2, "bg-".concat(bgVariant), bgVariant), _defineProperty(_class2, "border-".concat(borderVariant), borderVariant), _defineProperty(_class2, "border", borderVariant), _class2) }), $children); } }); var JumbotronPlugin = /*#__PURE__*/pluginFactory({ components: { BJumbotron: BJumbotron } }); var COMMON_ALIGNMENT = ['start', 'end', 'center']; // --- Helper methods --- // 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 = []; // --- Props --- // Prop generator for lazy generation of props var generateProps$2 = function generateProps() { // i.e. 'row-cols-2', 'row-cols-md-4', 'row-cols-xl-6', ... var rowColsProps = getBreakpointsUpCached().reduce(function (props, breakpoint) { props[suffixPropName(breakpoint, 'cols')] = makeProp(PROP_TYPE_NUMBER_STRING); return props; }, create(null)); // Cache the row-cols prop names rowColsPropList = keys(rowColsProps); // Return the generated props return makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, rowColsProps), {}, { alignContent: makeProp(PROP_TYPE_STRING, null, function (value) { return arrayIncludes(concat(COMMON_ALIGNMENT, 'between', 'around', 'stretch'), value); }), alignH: makeProp(PROP_TYPE_STRING, null, function (value) { return arrayIncludes(concat(COMMON_ALIGNMENT, 'between', 'around'), value); }), alignV: makeProp(PROP_TYPE_STRING, null, function (value) { return arrayIncludes(concat(COMMON_ALIGNMENT, 'baseline', 'stretch'), value); }), noGutters: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div') })), NAME_ROW); }; // --- Main component --- // 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: NAME_ROW, 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 alignV = props.alignV, alignH = props.alignH, alignContent = props.alignContent; // Loop through row-cols breakpoint props and generate the classes var classList = []; 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(alignV), alignV), _defineProperty(_classList$push, "justify-content-".concat(alignH), alignH), _defineProperty(_classList$push, "align-content-".concat(alignContent), 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$1m = makePropsConfigurable({ flush: makeProp(PROP_TYPE_BOOLEAN, false), horizontal: makeProp(PROP_TYPE_BOOLEAN_STRING, false), tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_LIST_GROUP); // --- Main component --- // @vue/component var BListGroup = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_LIST_GROUP, functional: true, props: props$1m, 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 actionTags = ['a', 'router-link', 'button', 'b-link']; // --- Props --- var linkProps$4 = omit(props$6, ['event', 'routerTag']); delete linkProps$4.href.default; delete linkProps$4.to.default; var props$1n = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps$4), {}, { action: makeProp(PROP_TYPE_BOOLEAN, false), button: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div'), variant: makeProp(PROP_TYPE_STRING) })), NAME_LIST_GROUP_ITEM); // --- Main component --- // @vue/component var BListGroupItem = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_LIST_GROUP_ITEM, functional: true, props: props$1n, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, children = _ref.children; var button = props.button, variant = props.variant, active = props.active, disabled = props.disabled; var link = isLink(props); var tag = button ? 'button' : !link ? props.tag : BLink; var action = !!(props.action || link || button || arrayIncludes(actionTags, props.tag)); var attrs = {}; var itemProps = {}; if (isTag(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$4, props); } return h(tag, a(data, { attrs: attrs, props: itemProps, staticClass: 'list-group-item', class: (_class = {}, _defineProperty(_class, "list-group-item-".concat(variant), variant), _defineProperty(_class, 'list-group-item-action', action), _defineProperty(_class, "active", active), _defineProperty(_class, "disabled", disabled), _class) }), children); } }); var ListGroupPlugin = /*#__PURE__*/pluginFactory({ components: { BListGroup: BListGroup, BListGroupItem: BListGroupItem } }); var props$1o = makePropsConfigurable({ right: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div'), verticalAlign: makeProp(PROP_TYPE_STRING, 'top') }, NAME_MEDIA_ASIDE); // --- Main component --- // @vue/component var BMediaAside = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_MEDIA_ASIDE, functional: true, props: props$1o, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children; var verticalAlign = props.verticalAlign; var align = verticalAlign === 'top' ? 'start' : verticalAlign === 'bottom' ? 'end' : /* istanbul ignore next */ verticalAlign; return h(props.tag, a(data, { staticClass: 'media-aside', class: _defineProperty({ 'media-aside-right': props.right }, "align-self-".concat(align), align) }), children); } }); var props$1p = makePropsConfigurable({ tag: makeProp(PROP_TYPE_STRING, 'div') }, NAME_MEDIA_BODY); // --- Main component --- // @vue/component var BMediaBody = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_MEDIA_BODY, functional: true, props: props$1p, 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$1q = makePropsConfigurable({ noBody: makeProp(PROP_TYPE_BOOLEAN, false), rightAlign: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div'), verticalAlign: makeProp(PROP_TYPE_STRING, 'top') }, NAME_MEDIA); // --- Main component --- // @vue/component var BMedia = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_MEDIA, functional: true, props: props$1q, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, slots = _ref.slots, scopedSlots = _ref.scopedSlots, children = _ref.children; var noBody = props.noBody, rightAlign = props.rightAlign, verticalAlign = props.verticalAlign; var $children = noBody ? children : []; if (!noBody) { var slotScope = {}; var $slots = slots(); var $scopedSlots = scopedSlots || {}; $children.push(h(BMediaBody, normalizeSlot(SLOT_NAME_DEFAULT, slotScope, $scopedSlots, $slots))); var $aside = normalizeSlot(SLOT_NAME_ASIDE, slotScope, $scopedSlots, $slots); if ($aside) { $children[rightAlign ? 'push' : 'unshift'](h(BMediaAside, { props: { right: rightAlign, verticalAlign: verticalAlign } }, $aside)); } } return h(props.tag, a(data, { staticClass: 'media' }), $children); } }); var MediaPlugin = /*#__PURE__*/pluginFactory({ components: { BMedia: BMedia, BMediaAside: BMediaAside, BMediaBody: BMediaBody } }); var PROP$1 = '$_bv_documentHandlers_'; // --- Mixin --- // @vue/component var listenOnDocumentMixin = Vue__default['default'].extend({ created: function created() { var _this = this; /* istanbul ignore next */ if (!IS_BROWSER) { 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_EVENT_NAME_BEFORE_DESTROY, 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 (eventName) { var handlers = items[eventName] || []; handlers.forEach(function (handler) { return eventOff(document, eventName, handler, EVENT_OPTIONS_NO_CAPTURE); }); }); }); }, methods: { listenDocument: function listenDocument(on, eventName, handler) { on ? this.listenOnDocument(eventName, handler) : this.listenOffDocument(eventName, handler); }, listenOnDocument: function listenOnDocument(eventName, handler) { if (this[PROP$1] && isString(eventName) && isFunction(handler)) { this[PROP$1][eventName] = this[PROP$1][eventName] || []; if (!arrayIncludes(this[PROP$1][eventName], handler)) { this[PROP$1][eventName].push(handler); eventOn(document, eventName, handler, EVENT_OPTIONS_NO_CAPTURE); } } }, listenOffDocument: function listenOffDocument(eventName, handler) { if (this[PROP$1] && isString(eventName) && isFunction(handler)) { eventOff(document, eventName, handler, EVENT_OPTIONS_NO_CAPTURE); this[PROP$1][eventName] = (this[PROP$1][eventName] || []).filter(function (h) { return h !== handler; }); } } } }); var PROP$2 = '$_bv_windowHandlers_'; // --- Mixin --- // @vue/component var listenOnWindowMixin = Vue__default['default'].extend({ 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 (IS_BROWSER) { 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 (eventName) { var handlers = items[eventName] || []; handlers.forEach(function (handler) { return eventOff(window, eventName, handler, EVENT_OPTIONS_NO_CAPTURE); }); }); } }, methods: { listenWindow: function listenWindow(on, eventName, handler) { on ? this.listenOnWindow(eventName, handler) : this.listenOffWindow(eventName, handler); }, listenOnWindow: function listenOnWindow(eventName, handler) { if (IS_BROWSER && this[PROP$2] && isString(eventName) && isFunction(handler)) { this[PROP$2][eventName] = this[PROP$2][eventName] || []; if (!arrayIncludes(this[PROP$2][eventName], handler)) { this[PROP$2][eventName].push(handler); eventOn(window, eventName, handler, EVENT_OPTIONS_NO_CAPTURE); } } }, listenOffWindow: function listenOffWindow(eventName, handler) { if (IS_BROWSER && this[PROP$2] && isString(eventName) && isFunction(handler)) { eventOff(window, eventName, handler, EVENT_OPTIONS_NO_CAPTURE); this[PROP$2][eventName] = (this[PROP$2][eventName] || []).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 scopedStyleMixin = Vue__default['default'].extend({ computed: { scopedStyleAttrs: function scopedStyleAttrs() { var scopeId = getScopeId(this.$parent); return scopeId ? _defineProperty({}, scopeId, '') : {}; } } }); // BVTransporter/BVTransporterTarget: // // 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 BVTransporter // Supports only a single root element // @vue/component var BVTransporterTarget = /*#__PURE__*/Vue__default['default'].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: NAME_TRANSPORTER_TARGET, props: { // Even though we only support a single root element, // VNodes are always passed as an array nodes: makeProp(PROP_TYPE_ARRAY_FUNCTION) }, data: function data(vm) { return { updatedNodes: vm.nodes }; }, destroyed: function destroyed() { removeNode(this.$el); }, render: function render(h) { var updatedNodes = this.updatedNodes; var $nodes = isFunction(updatedNodes) ? updatedNodes({}) : updatedNodes; $nodes = concat($nodes).filter(identity); if ($nodes && $nodes.length > 0 && !$nodes[0].text) { return $nodes[0]; } /* istanbul ignore next */ return h(); } }); // --- Props --- var props$1r = { // String: CSS selector, // HTMLElement: Element reference // Mainly needed for tooltips/popovers inside modals container: makeProp([HTMLElement, PROP_TYPE_STRING], 'body'), disabled: makeProp(PROP_TYPE_BOOLEAN, false), // This should be set to match the root element type tag: makeProp(PROP_TYPE_STRING, 'div') }; // --- Main component --- // @vue/component var BVTransporter = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TRANSPORTER, mixins: [normalizeSlotMixin], props: props$1r, watch: { disabled: { immediate: true, handler: function handler(disabled) { disabled ? this.unmountTarget() : this.$nextTick(this.mountTarget); } } }, created: function created() { // Create private non-reactive props this.$_defaultFn = null; this.$_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.$_defaultFn = null; }, methods: { // Get the element which the target should be appended to getContainer: function getContainer() { /* istanbul ignore else */ if (IS_BROWSER) { var container = this.container; return isString(container) ? select(container) : container; } else { return null; } }, // Mount the target mountTarget: function mountTarget() { if (!this.$_target) { var $container = this.getContainer(); if ($container) { var $el = document.createElement('div'); $container.appendChild($el); this.$_target = new BVTransporterTarget({ el: $el, parent: this, propsData: { // Initial nodes to be rendered nodes: concat(this.normalizeSlot()) } }); } } }, // Update the content of the target updateTarget: function updateTarget() { if (IS_BROWSER && this.$_target) { var defaultFn = this.$scopedSlots.default; if (!this.disabled) { /* istanbul ignore else: only applicable in Vue 2.5.x */ if (defaultFn && this.$_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.$_target.updatedNodes = defaultFn; } else if (!defaultFn) { // We also need to be back compatible with non-scoped default slot (i.e. 2.5.x) this.$_target.updatedNodes = this.$slots.default; } } // Update the scoped slot function cache this.$_defaultFn = defaultFn; } }, // Unmount the target unmountTarget: function unmountTarget() { this.$_target && this.$_target.$destroy(); this.$_target = null; } }, render: function render(h) { // This component has no root element, so only a single VNode is allowed if (this.disabled) { var $nodes = concat(this.normalizeSlot()).filter(identity); if ($nodes.length > 0 && !$nodes[0].text) { return $nodes[0]; } } return h(); } }); var BvModalEvent = /*#__PURE__*/function (_BvEvent) { _inherits(BvModalEvent, _BvEvent); var _super = _createSuper(BvModalEvent); function BvModalEvent(type) { var _this; var eventInit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, BvModalEvent); _this = _super.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(_objectSpread2({}, _get(_getPrototypeOf(BvModalEvent), "Defaults", this)), {}, { trigger: null }); } }]); return BvModalEvent; }(BvEvent); // Named exports /** * 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_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; var SELECTOR_STICKY_CONTENT = '.sticky-top'; var SELECTOR_NAVBAR_TOGGLER = '.navbar-toggler'; // --- Main component --- // @vue/component var ModalManager = /*#__PURE__*/Vue__default['default'].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 (IS_BROWSER) { 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(newValue) { var _this = this; this.checkScrollbar(); requestAF(function () { _this.updateModals(newValue || []); }); } }, 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_EVENT_NAME_BEFORE_DESTROY, 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) && IS_BROWSER) { // Create a temporary `div.modal-backdrop` to get computed z-index var div = document.createElement('div'); addClass(div, 'modal-backdrop'); addClass(div, 'd-none'); setStyle(div, '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) && IS_BROWSER) { // Create a temporary `div.measure-scrollbar` to get computed z-index var div = document.createElement('div'); addClass(div, '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_FIXED_CONTENT).forEach(function (el) { var actualPadding = getStyle(el, 'paddingRight') || ''; setAttr(el, 'data-padding-right', actualPadding); setStyle(el, 'paddingRight', "".concat(toFloat(getCS(el).paddingRight, 0) + scrollbarWidth, "px")); body._paddingChangedForModal.push(el); }); // Adjust sticky content margin /* istanbul ignore next: difficult to test in JSDOM */ selectAll(SELECTOR_STICKY_CONTENT).forEach(function (el) /* istanbul ignore next */ { var actualMargin = getStyle(el, 'marginRight') || ''; setAttr(el, 'data-margin-right', actualMargin); setStyle(el, 'marginRight', "".concat(toFloat(getCS(el).marginRight, 0) - scrollbarWidth, "px")); body._marginChangedForModal.push(el); }); // Adjust <b-navbar-toggler> margin /* istanbul ignore next: difficult to test in JSDOM */ selectAll(SELECTOR_NAVBAR_TOGGLER).forEach(function (el) /* istanbul ignore next */ { var actualMargin = getStyle(el, 'marginRight') || ''; setAttr(el, 'data-margin-right', actualMargin); setStyle(el, 'marginRight', "".concat(toFloat(getCS(el).marginRight, 0) + scrollbarWidth, "px")); body._marginChangedForModal.push(el); }); // Adjust body padding var actualPadding = getStyle(body, 'paddingRight') || ''; setAttr(body, 'data-padding-right', actualPadding); setStyle(body, 'paddingRight', "".concat(toFloat(getCS(body).paddingRight, 0) + 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')) { setStyle(el, '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')) { setStyle(el, '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')) { setStyle(body, 'paddingRight', getAttr(body, 'data-padding-right') || ''); removeAttr(body, 'data-padding-right'); } } } }); // Create and export our modal manager instance var modalManager = new ModalManager(); var _makeModelMixin$f = makeModelMixin('visible', { type: PROP_TYPE_BOOLEAN, defaultValue: false, event: EVENT_NAME_CHANGE }), modelMixin$e = _makeModelMixin$f.mixin, modelProps$e = _makeModelMixin$f.props, MODEL_PROP_NAME$e = _makeModelMixin$f.prop, MODEL_EVENT_NAME$e = _makeModelMixin$f.event; var TRIGGER_BACKDROP = 'backdrop'; var TRIGGER_ESC = 'esc'; var TRIGGER_FORCE = 'FORCE'; var TRIGGER_TOGGLE = 'toggle'; var BUTTON_CANCEL = 'cancel'; // TODO: This should be renamed to 'close' var BUTTON_CLOSE = 'headerclose'; var BUTTON_OK = 'ok'; var BUTTONS = [BUTTON_CANCEL, BUTTON_CLOSE, BUTTON_OK]; // `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'] }; // --- Props --- var props$1s = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$e), {}, { ariaLabel: makeProp(PROP_TYPE_STRING), autoFocusButton: makeProp(PROP_TYPE_STRING, null, /* istanbul ignore next */ function (value) { return isUndefinedOrNull(value) || arrayIncludes(BUTTONS, value); }), bodyBgVariant: makeProp(PROP_TYPE_STRING), bodyClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), bodyTextVariant: makeProp(PROP_TYPE_STRING), busy: makeProp(PROP_TYPE_BOOLEAN, false), buttonSize: makeProp(PROP_TYPE_STRING), cancelDisabled: makeProp(PROP_TYPE_BOOLEAN, false), cancelTitle: makeProp(PROP_TYPE_STRING, 'Cancel'), cancelTitleHtml: makeProp(PROP_TYPE_STRING), cancelVariant: makeProp(PROP_TYPE_STRING, 'secondary'), centered: makeProp(PROP_TYPE_BOOLEAN, false), contentClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), dialogClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), footerBgVariant: makeProp(PROP_TYPE_STRING), footerBorderVariant: makeProp(PROP_TYPE_STRING), footerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), footerTextVariant: makeProp(PROP_TYPE_STRING), headerBgVariant: makeProp(PROP_TYPE_STRING), headerBorderVariant: makeProp(PROP_TYPE_STRING), headerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), headerCloseContent: makeProp(PROP_TYPE_STRING, '×'), headerCloseLabel: makeProp(PROP_TYPE_STRING, 'Close'), headerCloseVariant: makeProp(PROP_TYPE_STRING), headerTextVariant: makeProp(PROP_TYPE_STRING), // TODO: Rename to `noBackdrop` and deprecate `hideBackdrop` hideBackdrop: makeProp(PROP_TYPE_BOOLEAN, false), // TODO: Rename to `noFooter` and deprecate `hideFooter` hideFooter: makeProp(PROP_TYPE_BOOLEAN, false), // TODO: Rename to `noHeader` and deprecate `hideHeader` hideHeader: makeProp(PROP_TYPE_BOOLEAN, false), // TODO: Rename to `noHeaderClose` and deprecate `hideHeaderClose` hideHeaderClose: makeProp(PROP_TYPE_BOOLEAN, false), ignoreEnforceFocusSelector: makeProp(PROP_TYPE_ARRAY_STRING), lazy: makeProp(PROP_TYPE_BOOLEAN, false), modalClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), noCloseOnBackdrop: makeProp(PROP_TYPE_BOOLEAN, false), noCloseOnEsc: makeProp(PROP_TYPE_BOOLEAN, false), noEnforceFocus: makeProp(PROP_TYPE_BOOLEAN, false), noFade: makeProp(PROP_TYPE_BOOLEAN, false), noStacking: makeProp(PROP_TYPE_BOOLEAN, false), okDisabled: makeProp(PROP_TYPE_BOOLEAN, false), okOnly: makeProp(PROP_TYPE_BOOLEAN, false), okTitle: makeProp(PROP_TYPE_STRING, 'OK'), okTitleHtml: makeProp(PROP_TYPE_STRING), okVariant: makeProp(PROP_TYPE_STRING, 'primary'), // HTML Element, CSS selector string or Vue component instance returnFocus: makeProp([HTMLElement, PROP_TYPE_OBJECT, PROP_TYPE_STRING]), scrollable: makeProp(PROP_TYPE_BOOLEAN, false), size: makeProp(PROP_TYPE_STRING, 'md'), static: makeProp(PROP_TYPE_BOOLEAN, false), title: makeProp(PROP_TYPE_STRING), titleClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), titleHtml: makeProp(PROP_TYPE_STRING), titleSrOnly: makeProp(PROP_TYPE_BOOLEAN, false), titleTag: makeProp(PROP_TYPE_STRING, 'h5') })), NAME_MODAL); // --- Main component --- // @vue/component var BModal = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_MODAL, mixins: [attrsMixin, idMixin, modelMixin$e, listenOnDocumentMixin, listenOnRootMixin, listenOnWindowMixin, normalizeSlotMixin, scopedStyleMixin], inheritAttrs: false, props: props$1s, 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, // The following items are controlled by the modalManager instance scrollbarWidth: 0, zIndex: modalManager.getBaseZIndex(), isTop: true, isBodyOverflowing: false }; }, computed: { modalId: function modalId() { return this.safeId(); }, modalOuterId: function modalOuterId() { return this.safeId('__BV_modal_outer_'); }, modalHeaderId: function modalHeaderId() { return this.safeId('__BV_modal_header_'); }, modalBodyId: function modalBodyId() { return this.safeId('__BV_modal_body_'); }, modalTitleId: function modalTitleId() { return this.safeId('__BV_modal_title_'); }, modalContentId: function modalContentId() { return this.safeId('__BV_modal_content_'); }, modalFooterId: function modalFooterId() { return this.safeId('__BV_modal_footer_'); }, modalBackdropId: function modalBackdropId() { return this.safeId('__BV_modal_backdrop_'); }, 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 { cancel: this.onCancel, close: this.onClose, hide: this.hide, ok: this.onOk, visible: this.isVisible }; }, computeIgnoreEnforceFocusSelector: function computeIgnoreEnforceFocusSelector() { // Normalize to an single selector with selectors separated by `,` return concat(this.ignoreEnforceFocusSelector).filter(identity).join(',').trim(); }, computedAttrs: function computedAttrs() { // 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 : {}; return _objectSpread2(_objectSpread2(_objectSpread2({}, scopedStyleAttrs), this.bvAttrs), {}, { id: this.modalOuterId }); }, computedModalAttrs: function computedModalAttrs() { var isVisible = this.isVisible, ariaLabel = this.ariaLabel; return { id: this.modalId, role: 'dialog', 'aria-hidden': isVisible ? null : 'true', 'aria-modal': isVisible ? 'true' : null, 'aria-label': ariaLabel, 'aria-labelledby': this.hideHeader || ariaLabel || // TODO: Rename slot to `title` and deprecate `modal-title` !(this.hasNormalizedSlot(SLOT_NAME_MODAL_TITLE) || this.titleHtml || this.title) ? null : this.modalTitleId, 'aria-describedby': this.modalBodyId }; } }, watch: _defineProperty({}, MODEL_PROP_NAME$e, function (newValue, oldValue) { if (newValue !== oldValue) { this[newValue ? 'show' : 'hide'](); } }), created: function created() { // Define non-reactive properties this.$_observer = null; this.$_returnFocus = this.returnFocus || 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(getRootActionEventName(NAME_MODAL, EVENT_NAME_SHOW), this.showHandler); this.listenOnRoot(getRootActionEventName(NAME_MODAL, EVENT_NAME_HIDE), this.hideHandler); this.listenOnRoot(getRootActionEventName(NAME_MODAL, EVENT_NAME_TOGGLE), this.toggleHandler); // Listen for `bv:modal::show events`, and close ourselves if the // opening modal not us this.listenOnRoot(getRootEventName(NAME_MODAL, EVENT_NAME_SHOW), this.modalListener); // Initially show modal? if (this[MODEL_PROP_NAME$e] === true) { this.$nextTick(this.show); } }, beforeDestroy: function beforeDestroy() { // Ensure everything is back to normal this.setObserver(false); if (this.isVisible) { this.isVisible = false; this.isShow = false; this.isTransitioning = false; } }, methods: { setObserver: function setObserver() { var on = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; this.$_observer && this.$_observer.disconnect(); this.$_observer = null; if (on) { this.$_observer = observeDom(this.$refs.content, this.checkModalOverflow.bind(this), OBSERVER_CONFIG); } }, // Private method to update the v-model updateModel: function updateModel(value) { if (value !== this[MODEL_PROP_NAME$e]) { this.$emit(MODEL_EVENT_NAME$e, value); } }, // 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(_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.modalId })); }, // 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(EVENT_NAME_HIDDEN, this.show); /* istanbul ignore next */ return; } this.isOpening = true; // Set the element to return focus to when closed this.$_returnFocus = this.$_returnFocus || this.getActiveElement(); var showEvt = this.buildEvent(EVENT_NAME_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(EVENT_NAME_HIDE, { cancelable: trigger !== TRIGGER_FORCE, trigger: trigger || null }); // We emit specific event for one of the three built-in buttons if (trigger === BUTTON_OK) { this.$emit(EVENT_NAME_OK, hideEvt); } else if (trigger === BUTTON_CANCEL) { this.$emit(EVENT_NAME_CANCEL, hideEvt); } else if (trigger === BUTTON_CLOSE) { this.$emit(EVENT_NAME_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 this.setObserver(false); // 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.$_returnFocus = triggerEl; } if (this.isVisible) { this.hide(TRIGGER_TOGGLE); } else { this.show(); } }, // Private method to get the current document active element getActiveElement: function getActiveElement$1() { // Returning focus to `document.body` may cause unwanted scrolls, // so we exclude setting focus on body var activeElement = getActiveElement(IS_BROWSER ? [document.body] : []); // 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. // 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 return activeElement && activeElement.focus ? activeElement : null; }, // 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(getRootEventName(NAME_MODAL, EVENT_NAME_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 () { // Observe changes in modal content and adjust if necessary // In a `$nextTick()` in case modal content is lazy _this.setObserver(true); }); }); }, // 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(EVENT_NAME_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(EVENT_NAME_HIDDEN)); }); }, emitEvent: function emitEvent(bvEvent) { var type = bvEvent.type; // We emit on `$root` first in case a global listener wants to cancel // the event first before the instance emits its event this.emitOnRoot(getRootEventName(NAME_MODAL, type), bvEvent, bvEvent.componentId); this.$emit(type, bvEvent); }, // 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(event) { eventOff(modal, 'mouseup', onceModalMouseup, EVENT_OPTIONS_NO_CAPTURE); if (event.target === modal) { _this5.ignoreBackdropClick = true; } }; eventOn(modal, 'mouseup', onceModalMouseup, EVENT_OPTIONS_NO_CAPTURE); }, onClickOut: function onClickOut(event) { 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, event.target)) { return; } // If backdrop clicked, hide modal if (!contains(this.$refs.content, event.target)) { this.hide(TRIGGER_BACKDROP); } }, onOk: function onOk() { this.hide(BUTTON_OK); }, onCancel: function onCancel() { this.hide(BUTTON_CANCEL); }, onClose: function onClose() { this.hide(BUTTON_CLOSE); }, onEsc: function onEsc(event) { // If ESC pressed, hide modal if (event.keyCode === CODE_ESC && this.isVisible && !this.noCloseOnEsc) { this.hide(TRIGGER_ESC); } }, // Document focusin listener focusHandler: function focusHandler(event) { // If focus leaves modal content, bring it back var content = this.$refs.content; var target = event.target; if (this.noEnforceFocus || !this.isTop || !this.isVisible || !content || document === target || contains(content, target) || this.computeIgnoreEnforceFocusSelector && closest(this.computeIgnoreEnforceFocusSelector, target, true)) { return; } var tabables = getTabables(this.$refs.content); var bottomTrap = this.$refs['bottom-trap']; var topTrap = this.$refs['top-trap']; 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 attemptFocus(content, { 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.modalId) { this.$_returnFocus = triggerEl || this.getActiveElement(); this.show(); } }, hideHandler: function hideHandler(id) { if (id === this.modalId) { this.hide('event'); } }, toggleHandler: function toggleHandler(id, triggerEl) { if (id === this.modalId) { this.toggle(triggerEl); } }, modalListener: function modalListener(bvEvent) { // If another modal opens, close this one if stacking not permitted if (this.noStacking && bvEvent.vueTarget !== this) { this.hide(); } }, // Focus control handlers focusFirst: function focusFirst() { var _this6 = this; // Don't try and focus if we are SSR if (IS_BROWSER) { 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; /* istanbul ignore next */ var el = autoFocus === BUTTON_OK && ok ? ok.$el || ok : autoFocus === BUTTON_CANCEL && cancel ? cancel.$el || cancel : autoFocus === BUTTON_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.$_returnFocus || null; this.$_returnFocus = 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) { // TODO: Rename slot to `header` and deprecate `modal-header` var $modalHeader = this.normalizeSlot(SLOT_NAME_MODAL_HEADER, this.slotScope); if (!$modalHeader) { var $closeButton = h(); if (!this.hideHeaderClose) { $closeButton = h(BButtonClose, { props: { content: this.headerCloseContent, disabled: this.isTransitioning, ariaLabel: this.headerCloseLabel, textVariant: this.headerCloseVariant || this.headerTextVariant }, on: { click: this.onClose }, ref: 'close-button' }, // TODO: Rename slot to `header-close` and deprecate `modal-header-close` [this.normalizeSlot(SLOT_NAME_MODAL_HEADER_CLOSE)]); } $modalHeader = [h(this.titleTag, { staticClass: 'modal-title', class: this.titleClasses, attrs: { id: this.modalTitleId }, // TODO: Rename slot to `title` and deprecate `modal-title` domProps: this.hasNormalizedSlot(SLOT_NAME_MODAL_TITLE) ? {} : htmlOrText(this.titleHtml, this.title) }, // TODO: Rename slot to `title` and deprecate `modal-title` this.normalizeSlot(SLOT_NAME_MODAL_TITLE, this.slotScope)), $closeButton]; } $header = h('header', { staticClass: 'modal-header', class: this.headerClasses, attrs: { id: this.modalHeaderId }, ref: 'header' }, [$modalHeader]); } // Modal body var $body = h('div', { staticClass: 'modal-body', class: this.bodyClasses, attrs: { id: this.modalBodyId }, ref: 'body' }, this.normalizeSlot(SLOT_NAME_DEFAULT, this.slotScope)); // Modal footer var $footer = h(); if (!this.hideFooter) { // TODO: Rename slot to `footer` and deprecate `modal-footer` var $modalFooter = this.normalizeSlot(SLOT_NAME_MODAL_FOOTER, this.slotScope); if (!$modalFooter) { var $cancelButton = h(); if (!this.okOnly) { $cancelButton = h(BButton, { props: { variant: this.cancelVariant, size: this.buttonSize, disabled: this.cancelDisabled || this.busy || this.isTransitioning }, // TODO: Rename slot to `cancel-button` and deprecate `modal-cancel` domProps: this.hasNormalizedSlot(SLOT_NAME_MODAL_CANCEL) ? {} : htmlOrText(this.cancelTitleHtml, this.cancelTitle), on: { click: this.onCancel }, ref: 'cancel-button' }, // TODO: Rename slot to `cancel-button` and deprecate `modal-cancel` this.normalizeSlot(SLOT_NAME_MODAL_CANCEL)); } var $okButton = h(BButton, { props: { variant: this.okVariant, size: this.buttonSize, disabled: this.okDisabled || this.busy || this.isTransitioning }, // TODO: Rename slot to `ok-button` and deprecate `modal-ok` domProps: this.hasNormalizedSlot(SLOT_NAME_MODAL_OK) ? {} : htmlOrText(this.okTitleHtml, this.okTitle), on: { click: this.onOk }, ref: 'ok-button' }, // TODO: Rename slot to `ok-button` and deprecate `modal-ok` this.normalizeSlot(SLOT_NAME_MODAL_OK)); $modalFooter = [$cancelButton, $okButton]; } $footer = h('footer', { staticClass: 'modal-footer', class: this.footerClasses, attrs: { id: this.modalFooterId }, ref: 'footer' }, [$modalFooter]); } // Assemble modal content var $modalContent = h('div', { staticClass: 'modal-content', class: this.contentClass, attrs: { id: this.modalContentId, tabindex: '-1' }, ref: 'content' }, [$header, $body, $footer]); // Tab traps 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', { attrs: { tabindex: '0' }, ref: 'top-trap' }); $tabTrapBottom = h('span', { attrs: { tabindex: '0' }, ref: 'bottom-trap' }); } // Modal dialog wrapper var $modalDialog = h('div', { staticClass: 'modal-dialog', class: this.dialogClasses, on: { mousedown: this.onDialogMousedown }, ref: 'dialog' }, [$tabTrapTop, $modalContent, $tabTrapBottom]); // Modal var $modal = h('div', { staticClass: 'modal', class: this.modalClasses, style: this.modalStyles, attrs: this.computedModalAttrs, on: { keydown: this.onEsc, click: this.onClickOut }, directives: [{ name: 'show', value: this.isVisible }], ref: 'modal' }, [$modalDialog]); // Wrap modal in transition // Sadly, we can't use `BVTransition` here due to the differences in // transition durations for `.modal` and `.modal-dialog` // At least until 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.modalBackdropId } }, // TODO: Rename slot to `backdrop` and deprecate `modal-backdrop` this.normalizeSlot(SLOT_NAME_MODAL_BACKDROP)); } $backdrop = h(BVTransition, { props: { noFade: this.noFade } }, [$backdrop]); // Assemble modal and backdrop in an outer <div> return h('div', { style: this.modalOuterStyle, attrs: this.computedAttrs, key: "modal-outer-".concat(this[COMPONENT_UID_KEY]) }, [$modal, $backdrop]); } }, render: function render(h) { if (this.static) { return this.lazy && this.isHidden ? h() : this.makeModal(h); } else { return this.isHidden ? h() : h(BVTransporter, [this.makeModal(h)]); } } }); var ROOT_ACTION_EVENT_NAME_SHOW = getRootActionEventName(NAME_MODAL, EVENT_NAME_SHOW); // 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(event) { // `currentTarget` is the element with the listener on it var currentTarget = event.currentTarget; if (!isDisabled(currentTarget)) { var type = event.type; var key = event.keyCode; // Open modal only if trigger is not disabled if (type === 'click' || type === 'keydown' && (key === CODE_ENTER || key === CODE_SPACE)) { vnode.context.$root.$emit(ROOT_ACTION_EVENT_NAME_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$1 = '$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$1s, ['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' }; // --- Helper 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: NAME_MSG_BOX, 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() { _this.$nextTick(function () { // In a `requestAF()` to release control back to application requestAF(function () { _this.$destroy(); }); }); }; // Self destruct if parent destroyed this.$parent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy); // Self destruct after hidden this.$once(EVENT_NAME_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_EVENT_NAME_BEFORE_DESTROY, 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$1) || warnNoPromiseSupport(PROP_NAME$1)) { /* 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(_objectSpread2(_objectSpread2({}, filterOptions(getComponentConfig(NAME_MODAL))), {}, { // 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_EVENT_NAME_DESTROYED, function () { if (!resolved) { /* istanbul ignore next */ reject(new Error('BootstrapVue MsgBox destroyed before resolve')); } }); msgBox.$on(EVENT_NAME_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 ? arguments[3] : null; if (!content || warnNoPromiseSupport(PROP_NAME$1) || warnNotClient(PROP_NAME$1) || !isFunction(resolver)) { /* istanbul ignore next */ return; } return asyncMsgBox($parent, _objectSpread2(_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, [getRootActionEventName(NAME_MODAL, 'show'), 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, [getRootActionEventName(NAME_MODAL, 'hide'), 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(_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(_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 if (!hasOwnProperty(Vue.prototype, PROP_NAME$1)) { defineProperty(Vue.prototype, PROP_NAME$1, { get: function get() { /* istanbul ignore next */ if (!this || !this[PROP_NAME_PRIV]) { warn("\"".concat(PROP_NAME$1, "\" must be accessed from a Vue instance \"this\" context."), NAME_MODAL); } 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 computeJustifyContent = function computeJustifyContent(value) { value = value === 'left' ? 'start' : value === 'right' ? 'end' : value; return "justify-content-".concat(value); }; // --- Props --- var props$1t = makePropsConfigurable({ align: makeProp(PROP_TYPE_STRING), // Set to `true` if placing in a card header cardHeader: makeProp(PROP_TYPE_BOOLEAN, false), fill: makeProp(PROP_TYPE_BOOLEAN, false), justified: makeProp(PROP_TYPE_BOOLEAN, false), pills: makeProp(PROP_TYPE_BOOLEAN, false), small: makeProp(PROP_TYPE_BOOLEAN, false), tabs: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'ul'), vertical: makeProp(PROP_TYPE_BOOLEAN, false) }, NAME_NAV); // --- Main component --- // @vue/component var BNav = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAV, functional: true, props: props$1t, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, children = _ref.children; var tabs = props.tabs, pills = props.pills, vertical = props.vertical, align = props.align, cardHeader = props.cardHeader; return h(props.tag, a(data, { staticClass: 'nav', class: (_class = { 'nav-tabs': tabs, 'nav-pills': pills && !tabs, 'card-header-tabs': !vertical && cardHeader && tabs, 'card-header-pills': !vertical && cardHeader && pills && !tabs, 'flex-column': vertical, 'nav-fill': !vertical && props.fill, 'nav-justified': !vertical && props.justified }, _defineProperty(_class, computeJustifyContent(align), !vertical && align), _defineProperty(_class, "small", props.small), _class) }), children); } }); var linkProps$5 = omit(props$6, ['event', 'routerTag']); var props$1u = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps$5), {}, { linkAttrs: makeProp(PROP_TYPE_OBJECT, {}), linkClasses: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING) })), NAME_NAV_ITEM); // --- Main component --- // @vue/component var BNavItem = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAV_ITEM, functional: true, props: props$1u, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, listeners = _ref.listeners, children = _ref.children; return h('li', a(omit(data, ['on']), { staticClass: 'nav-item' }), [h(BLink, { staticClass: 'nav-link', class: props.linkClasses, attrs: props.linkAttrs, props: pluckProps(linkProps$5, props), on: listeners }, children)]); } }); var props$1v = {}; // --- Main component --- // @vue/component var BNavText = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAV_TEXT, functional: true, props: props$1v, render: function render(h, _ref) { var data = _ref.data, children = _ref.children; return h('li', a(data, { staticClass: 'navbar-text' }), children); } }); var formProps = omit(props$F, ['inline']); var props$1w = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, formProps), {}, { formClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING) })), NAME_NAV_FORM); // --- Main component --- // @vue/component var BNavForm = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAV_FORM, functional: true, props: props$1w, render: function render(h, _ref) { var props = _ref.props, data = _ref.data, children = _ref.children, listeners = _ref.listeners; var $form = h(BForm, { class: props.formClass, props: _objectSpread2(_objectSpread2({}, pluckProps(formProps, props)), {}, { inline: true }), attrs: data.attrs, on: listeners }, children); return h('li', a(omit(data, ['attrs', 'on']), { staticClass: 'form-inline' }), [$form]); } }); var props$1x = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$g), pick(props$A, [].concat(_toConsumableArray(keys(props$z)), ['html', 'lazy', 'menuClass', 'noCaret', 'role', 'text', 'toggleClass'])))), NAME_NAV_ITEM_DROPDOWN); // --- Main component --- // @vue/component var BNavItemDropdown = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAV_ITEM_DROPDOWN, mixins: [idMixin, dropdownMixin, normalizeSlotMixin], props: props$1x, computed: { toggleId: function toggleId() { return this.safeId('_BV_toggle_'); }, dropdownClasses: function dropdownClasses() { return [this.directionClass, this.boundaryClass, { 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 toggleId = this.toggleId, visible = this.visible, hide = this.hide; var $toggle = h(BLink, { staticClass: 'nav-link dropdown-toggle', class: this.toggleClasses, props: { href: "#".concat(this.id || ''), disabled: this.disabled }, attrs: { id: toggleId, role: 'button', 'aria-haspopup': 'true', 'aria-expanded': visible ? 'true' : 'false' }, on: { mousedown: this.onMousedown, click: this.toggle, keydown: this.toggle // Handle ENTER, SPACE and DOWN }, ref: 'toggle' }, [// TODO: The `text` slot is deprecated in favor of the `button-content` slot this.normalizeSlot([SLOT_NAME_BUTTON_CONTENT, SLOT_NAME_TEXT]) || h('span', { domProps: htmlOrText(this.html, this.text) })]); var $menu = h('ul', { staticClass: 'dropdown-menu', class: this.menuClasses, attrs: { tabindex: '-1', 'aria-labelledby': toggleId }, on: { keydown: this.onKeydown // Handle UP, DOWN and ESC }, ref: 'menu' }, !this.lazy || visible ? this.normalizeSlot(SLOT_NAME_DEFAULT, { hide: hide }) : [h()]); return h('li', { staticClass: 'nav-item b-nav-dropdown dropdown', class: this.dropdownClasses, attrs: { id: this.safeId() } }, [$toggle, $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 props$1y = makePropsConfigurable({ fixed: makeProp(PROP_TYPE_STRING), print: makeProp(PROP_TYPE_BOOLEAN, false), sticky: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'nav'), toggleable: makeProp(PROP_TYPE_BOOLEAN_STRING, false), type: makeProp(PROP_TYPE_STRING, 'light'), variant: makeProp(PROP_TYPE_STRING) }, NAME_NAVBAR); // --- Main component --- // @vue/component var BNavbar = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAVBAR, mixins: [normalizeSlotMixin], provide: function provide() { return { bvNavbar: this }; }, props: props$1y, computed: { breakpointClass: function breakpointClass() { var toggleable = this.toggleable; var xs = getBreakpoints()[0]; var breakpoint = null; 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; var tag = this.tag, type = this.type, variant = this.variant, fixed = this.fixed; return h(tag, { staticClass: 'navbar', class: [(_ref = { 'd-print': this.print, 'sticky-top': this.sticky }, _defineProperty(_ref, "navbar-".concat(type), type), _defineProperty(_ref, "bg-".concat(variant), variant), _defineProperty(_ref, "fixed-".concat(fixed), fixed), _ref), this.breakpointClass], attrs: { role: isTag(tag, 'nav') ? null : 'navigation' } }, [this.normalizeSlot()]); } }); var computeJustifyContent$1 = function computeJustifyContent(value) { value = value === 'left' ? 'start' : value === 'right' ? 'end' : value; return "justify-content-".concat(value); }; // --- Props --- var props$1z = makePropsConfigurable(pick(props$1t, ['tag', 'fill', 'justified', 'align', 'small']), NAME_NAVBAR_NAV); // --- Main component --- // @vue/component var BNavbarNav = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAVBAR_NAV, functional: true, props: props$1z, render: function render(h, _ref) { var _class; var props = _ref.props, data = _ref.data, children = _ref.children; var align = props.align; return h(props.tag, a(data, { staticClass: 'navbar-nav', class: (_class = { 'nav-fill': props.fill, 'nav-justified': props.justified }, _defineProperty(_class, computeJustifyContent$1(align), align), _defineProperty(_class, "small", props.small), _class) }), children); } }); var linkProps$6 = omit(props$6, ['event', 'routerTag']); linkProps$6.href.default = undefined; linkProps$6.to.default = undefined; var props$1A = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, linkProps$6), {}, { tag: makeProp(PROP_TYPE_STRING, 'div') })), NAME_NAVBAR_BRAND); // --- Main component --- // @vue/component var BNavbarBrand = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAVBAR_BRAND, functional: true, props: props$1A, 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$6, props) : {} }), children); } }); var CLASS_NAME$2 = 'navbar-toggler'; var ROOT_EVENT_NAME_STATE$2 = getRootEventName(NAME_COLLAPSE, 'state'); var ROOT_EVENT_NAME_SYNC_STATE$2 = getRootEventName(NAME_COLLAPSE, 'sync-state'); // --- Props --- var props$1B = makePropsConfigurable({ disabled: makeProp(PROP_TYPE_BOOLEAN, false), label: makeProp(PROP_TYPE_STRING, 'Toggle navigation'), target: makeProp(PROP_TYPE_ARRAY_STRING, undefined, true) // Required }, NAME_NAVBAR_TOGGLE); // --- Main component --- // @vue/component var BNavbarToggle = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_NAVBAR_TOGGLE, directives: { VBToggle: VBToggle }, mixins: [listenOnRootMixin, normalizeSlotMixin], props: props$1B, data: function data() { return { toggleState: false }; }, created: function created() { this.listenOnRoot(ROOT_EVENT_NAME_STATE$2, this.handleStateEvt); this.listenOnRoot(ROOT_EVENT_NAME_SYNC_STATE$2, this.handleStateEvt); }, methods: { onClick: function onClick(event) { if (!this.disabled) { // Emit courtesy `click` event this.$emit(EVENT_NAME_CLICK, event); } }, handleStateEvt: function handleStateEvt(id, state) { // We listen for state events so that we can pass the // boolean expanded state to the default scoped slot if (id === this.target) { this.toggleState = state; } } }, render: function render(h) { var disabled = this.disabled; return h('button', { staticClass: CLASS_NAME$2, class: { disabled: disabled }, directives: [{ name: 'VBToggle', value: this.target }], attrs: { type: 'button', disabled: disabled, 'aria-label': this.label }, on: { click: this.onClick } }, [this.normalizeSlot(SLOT_NAME_DEFAULT, { expanded: this.toggleState }) || h('span', { staticClass: "".concat(CLASS_NAME$2, "-icon") })]); } }); var NavbarPlugin = /*#__PURE__*/pluginFactory({ components: { BNavbar: BNavbar, BNavbarNav: BNavbarNav, BNavbarBrand: BNavbarBrand, BNavbarToggle: BNavbarToggle, BNavToggle: BNavbarToggle }, plugins: { NavPlugin: NavPlugin, CollapsePlugin: CollapsePlugin, DropdownPlugin: DropdownPlugin } }); var props$1C = makePropsConfigurable({ label: makeProp(PROP_TYPE_STRING), role: makeProp(PROP_TYPE_STRING, 'status'), small: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'span'), type: makeProp(PROP_TYPE_STRING, 'border'), variant: makeProp(PROP_TYPE_STRING) }, NAME_SPINNER); // --- Main component --- // @vue/component var BSpinner = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SPINNER, functional: true, props: props$1C, 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(SLOT_NAME_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 POSITION_COVER = { top: 0, left: 0, bottom: 0, right: 0 }; // --- Props --- var props$1D = makePropsConfigurable({ // Alternative to variant, allowing a specific // CSS color to be applied to the overlay bgColor: makeProp(PROP_TYPE_STRING), blur: makeProp(PROP_TYPE_STRING, '2px'), fixed: makeProp(PROP_TYPE_BOOLEAN, false), noCenter: makeProp(PROP_TYPE_BOOLEAN, false), noFade: makeProp(PROP_TYPE_BOOLEAN, false), // If `true, does not render the default slot // and switches to absolute positioning noWrap: makeProp(PROP_TYPE_BOOLEAN, false), opacity: makeProp(PROP_TYPE_NUMBER_STRING, 0.85, function (value) { var number = toFloat(value, 0); return number >= 0 && number <= 1; }), overlayTag: makeProp(PROP_TYPE_STRING, 'div'), rounded: makeProp(PROP_TYPE_BOOLEAN_STRING, false), show: makeProp(PROP_TYPE_BOOLEAN, false), spinnerSmall: makeProp(PROP_TYPE_BOOLEAN, false), spinnerType: makeProp(PROP_TYPE_STRING, 'border'), spinnerVariant: makeProp(PROP_TYPE_STRING), variant: makeProp(PROP_TYPE_STRING, 'light'), wrapTag: makeProp(PROP_TYPE_STRING, 'div'), zIndex: makeProp(PROP_TYPE_NUMBER_STRING, 10) }, NAME_OVERLAY); // --- Main component --- // @vue/component var BOverlay = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_OVERLAY, mixins: [normalizeSlotMixin], props: props$1D, computed: { computedRounded: function computedRounded() { var rounded = this.rounded; return rounded === true || rounded === '' ? 'rounded' : !rounded ? '' : "rounded-".concat(rounded); }, computedVariant: function computedVariant() { var variant = this.variant; return variant && !this.bgColor ? "bg-".concat(variant) : ''; }, slotScope: function slotScope() { return { spinnerType: this.spinnerType || null, spinnerVariant: this.spinnerVariant || null, spinnerSmall: this.spinnerSmall }; } }, methods: { defaultOverlayFn: function defaultOverlayFn(_ref) { var spinnerType = _ref.spinnerType, spinnerVariant = _ref.spinnerVariant, spinnerSmall = _ref.spinnerSmall; return this.$createElement(BSpinner, { props: { type: spinnerType, variant: spinnerVariant, small: spinnerSmall } }); } }, render: function render(h) { var _this = this; var show = this.show, fixed = this.fixed, noFade = this.noFade, noWrap = this.noWrap, slotScope = this.slotScope; var $overlay = h(); if (show) { var $background = h('div', { staticClass: 'position-absolute', class: [this.computedVariant, this.computedRounded], style: _objectSpread2(_objectSpread2({}, POSITION_COVER), {}, { opacity: this.opacity, backgroundColor: this.bgColor || null, backdropFilter: this.blur ? "blur(".concat(this.blur, ")") : null }) }); var $content = h('div', { staticClass: 'position-absolute', style: this.noCenter ? /* istanbul ignore next */ _objectSpread2({}, POSITION_COVER) : { top: '50%', left: '50%', transform: 'translateX(-50%) translateY(-50%)' } }, [this.normalizeSlot(SLOT_NAME_OVERLAY, slotScope) || this.defaultOverlayFn(slotScope)]); $overlay = h(this.overlayTag, { staticClass: 'b-overlay', class: { 'position-absolute': !noWrap || noWrap && !fixed, 'position-fixed': noWrap && fixed }, style: _objectSpread2(_objectSpread2({}, POSITION_COVER), {}, { zIndex: this.zIndex || 10 }), on: { click: function click(event) { return _this.$emit(EVENT_NAME_CLICK, event); } }, key: 'overlay' }, [$background, $content]); } // Wrap in a fade transition $overlay = h(BVTransition, { props: { noFade: noFade, appear: true }, on: { 'after-enter': function afterEnter() { return _this.$emit(EVENT_NAME_SHOWN); }, 'after-leave': function afterLeave() { return _this.$emit(EVENT_NAME_HIDDEN); } } }, [$overlay]); if (noWrap) { return $overlay; } return h(this.wrapTag, { staticClass: 'b-overlay-wrap position-relative', attrs: { 'aria-busy': show ? 'true' : null } }, noWrap ? [$overlay] : [this.normalizeSlot(), $overlay]); } }); var OverlayPlugin = /*#__PURE__*/pluginFactory({ components: { BOverlay: BOverlay } }); var _watch$e; // for `<b-pagination>` and `<b-pagination-nav>` // --- Constants --- var _makeModelMixin$g = makeModelMixin('value', { type: PROP_TYPE_BOOLEAN_NUMBER_STRING, defaultValue: null, /* istanbul ignore next */ validator: function validator(value) { if (!isNull(value) && toInteger(value, 0) < 1) { warn('"v-model" value must be a number greater than "0"', NAME_PAGINATION); return false; } return true; } }), modelMixin$f = _makeModelMixin$g.mixin, modelProps$f = _makeModelMixin$g.props, MODEL_PROP_NAME$f = _makeModelMixin$g.prop, MODEL_EVENT_NAME$f = _makeModelMixin$g.event; 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 createArray(numberOfPages, function (_, i) { return { number: startNumber + i, classes: null }; }); }; // Sanitize the provided limit value (converting to a number) var sanitizeLimit = function sanitizeLimit(value) { var limit = toInteger(value) || 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(event) { if (event.keyCode === CODE_SPACE) { // Stop page from scrolling stopEvent(event, { immediatePropagation: true }); // Trigger the click event on the link event.currentTarget.click(); return false; } }; // --- Props --- var props$1E = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, modelProps$f), {}, { align: makeProp(PROP_TYPE_STRING, 'left'), ariaLabel: makeProp(PROP_TYPE_STRING, 'Pagination'), disabled: makeProp(PROP_TYPE_BOOLEAN, false), ellipsisClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), ellipsisText: makeProp(PROP_TYPE_STRING, "\u2026"), // '…' firstClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), firstNumber: makeProp(PROP_TYPE_BOOLEAN, false), firstText: makeProp(PROP_TYPE_STRING, "\xAB"), // '«' hideEllipsis: makeProp(PROP_TYPE_BOOLEAN, false), hideGotoEndButtons: makeProp(PROP_TYPE_BOOLEAN, false), labelFirstPage: makeProp(PROP_TYPE_STRING, 'Go to first page'), labelLastPage: makeProp(PROP_TYPE_STRING, 'Go to last page'), labelNextPage: makeProp(PROP_TYPE_STRING, 'Go to next page'), labelPage: makeProp(PROP_TYPE_FUNCTION_STRING, 'Go to page'), labelPrevPage: makeProp(PROP_TYPE_STRING, 'Go to previous page'), lastClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), lastNumber: makeProp(PROP_TYPE_BOOLEAN, false), lastText: makeProp(PROP_TYPE_STRING, "\xBB"), // '»' limit: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_LIMIT, /* istanbul ignore next */ function (value) { if (toInteger(value, 0) < 1) { warn('Prop "limit" must be a number greater than "0"', NAME_PAGINATION); return false; } return true; }), nextClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), nextText: makeProp(PROP_TYPE_STRING, "\u203A"), // '›' pageClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), pills: makeProp(PROP_TYPE_BOOLEAN, false), prevClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), prevText: makeProp(PROP_TYPE_STRING, "\u2039"), // '‹' size: makeProp(PROP_TYPE_STRING) })), 'pagination'); // --- Mixin --- // @vue/component var paginationMixin = Vue__default['default'].extend({ mixins: [modelMixin$f, normalizeSlotMixin], props: props$1E, data: function data() { // `-1` signifies no page initially selected var currentPage = toInteger(this[MODEL_PROP_NAME$f], 0); currentPage = currentPage > 0 ? currentPage : -1; return { currentPage: currentPage, localNumberOfPages: 1, localLimit: DEFAULT_LIMIT }; }, computed: { btnSize: function btnSize() { var size = this.size; return size ? "pagination-".concat(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, numberOfPages = this.localNumberOfPages, currentPage = this.computedCurrentPage, hideEllipsis = this.hideEllipsis, firstNumber = this.firstNumber, 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 = mathMin(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 - (hideEllipsis ? 0 : 2); showFirstDots = !!(!hideEllipsis || firstNumber); showLastDots = !!(!hideEllipsis || lastNumber); } startNumber = currentPage - mathFloor(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 = mathMin(numberOfLinks + 1, numberOfPages, limit + 1); } else if (lastNumber && numberOfPages === startNumber + numberOfLinks - 1) { startNumber = mathMax(startNumber - 1, 1); numberOfLinks = mathMin(numberOfPages - startNumber + 1, numberOfPages, limit + 1); } } numberOfLinks = mathMin(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: (_watch$e = {}, _defineProperty(_watch$e, MODEL_PROP_NAME$f, function (newValue, oldValue) { if (newValue !== oldValue) { this.currentPage = sanitizeCurrentPage(newValue, this.localNumberOfPages); } }), _defineProperty(_watch$e, "currentPage", function currentPage(newValue, oldValue) { if (newValue !== oldValue) { // Emit `null` if no page selected this.$emit(MODEL_EVENT_NAME$f, newValue > 0 ? newValue : null); } }), _defineProperty(_watch$e, "limit", function limit(newValue, oldValue) { if (newValue !== oldValue) { this.localLimit = sanitizeLimit(newValue); } }), _watch$e), 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(event) { var keyCode = event.keyCode, shiftKey = event.shiftKey; /* istanbul ignore if */ if (this.isNav) { // We disable left/right keyboard navigation in `<b-pagination-nav>` return; } if (keyCode === CODE_LEFT || keyCode === CODE_UP) { stopEvent(event, { propagation: false }); shiftKey ? this.focusFirst() : this.focusPrev(); } else if (keyCode === CODE_RIGHT || keyCode === CODE_DOWN) { stopEvent(event, { propagation: false }); 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); }); }, 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'), 0) === _this2.computedCurrentPage; }); if (!attemptFocus(btn)) { // 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); }); attemptFocus(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); }); attemptFocus(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 index = buttons.indexOf(getActiveElement()); if (index > 0 && !isDisabled(buttons[index - 1])) { attemptFocus(buttons[index - 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 index = buttons.indexOf(getActiveElement()); if (index < buttons.length - 1 && !isDisabled(buttons[index + 1])) { attemptFocus(buttons[index + 1]); } }); } }, render: function render(h) { var _this7 = this; var disabled = this.disabled, labelPage = this.labelPage, ariaLabel = this.ariaLabel, isNav = this.isNav, numberOfPages = this.localNumberOfPages, currentPage = this.computedCurrentPage; var pageNumbers = this.pageList.map(function (p) { return p.number; }); var _this$paginationParam2 = this.paginationParams, showFirstDots = _this$paginationParam2.showFirstDots, showLastDots = _this$paginationParam2.showLastDots; var fill = this.align === 'fill'; var $buttons = []; // 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(event) { _this7.onClick(event, linkTo); }, 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', { staticClass: 'page-item', class: ['disabled', 'bv-d-xs-down-none', fill ? 'flex-fill' : '', _this7.ellipsisClass], attrs: { role: 'separator' }, key: "ellipsis-".concat(isLast ? 'last' : 'first') }, [h('span', { staticClass: 'page-link' }, [_this7.normalizeSlot(SLOT_NAME_ELLIPSIS_TEXT) || toString$1(_this7.ellipsisText) || h()])]); }; // Page button factory var makePageButton = function makePageButton(page, idx) { var pageNumber = page.number; var active = isActivePage(pageNumber) && !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': hasPropFunction(labelPage) ? /* istanbul ignore next */ labelPage(pageNumber) : "".concat(isFunction(labelPage) ? labelPage() : labelPage, " ").concat(pageNumber), 'aria-checked': isNav ? null : active ? 'true' : 'false', 'aria-current': isNav && active ? 'page' : null, 'aria-posinset': isNav ? null : pageNumber, 'aria-setsize': isNav ? null : numberOfPages, // ARIA "roving tabindex" method (except in `isNav` mode) tabindex: isNav ? null : tabIndex }; var btnContent = toString$1(_this7.makePage(pageNumber)); var scope = { page: pageNumber, index: pageNumber - 1, content: btnContent, active: active, disabled: disabled }; var $inner = h(disabled ? 'span' : isNav ? BLink : 'button', { props: disabled || !isNav ? {} : _this7.linkProps(pageNumber), staticClass: 'page-link', class: { 'flex-grow-1': !isNav && !disabled && fill }, attrs: attrs, on: disabled ? {} : { '!click': function click(event) { _this7.onClick(event, pageNumber); }, keydown: onSpaceKey } }, [_this7.normalizeSlot(SLOT_NAME_PAGE, scope) || btnContent]); return h('li', { 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' }, key: "page-".concat(pageNumber) }, [$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, SLOT_NAME_FIRST_TEXT, this.firstText, this.firstClass, 1, 'pagination-goto-first'); } $buttons.push($firstPageBtn); // Goto previous page button $buttons.push(makeEndBtn(currentPage - 1, this.labelPrevPage, SLOT_NAME_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, SLOT_NAME_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, SLOT_NAME_LAST_TEXT, this.lastText, this.lastClass, numberOfPages, 'pagination-goto-last'); } $buttons.push($lastPageBtn); // Assemble the pagination buttons var $pagination = h('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 : ariaLabel || null }, // We disable keyboard left/right nav when `<b-pagination-nav>` on: isNav ? {} : { keydown: this.handleKeyNav }, ref: 'ul' }, $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 ? ariaLabel || null : null } }, [$pagination]); } return $pagination; } }); var DEFAULT_PER_PAGE = 20; var DEFAULT_TOTAL_ROWS = 0; // --- Helper methods --- // Sanitize the provided per page number (converting to a number) var sanitizePerPage = function sanitizePerPage(value) { return mathMax(toInteger(value) || DEFAULT_PER_PAGE, 1); }; // Sanitize the provided total rows number (converting to a number) var sanitizeTotalRows = function sanitizeTotalRows(value) { return mathMax(toInteger(value) || DEFAULT_TOTAL_ROWS, 0); }; // --- Props --- var props$1F = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$1E), {}, { ariaControls: makeProp(PROP_TYPE_STRING), perPage: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_PER_PAGE), totalRows: makeProp(PROP_TYPE_NUMBER_STRING, DEFAULT_TOTAL_ROWS) })), NAME_PAGINATION); // --- Main component --- // @vue/component var BPagination = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_PAGINATION, // The render function is brought in via the `paginationMixin` mixins: [paginationMixin], props: props$1F, computed: { numberOfPages: function numberOfPages() { var result = mathCeil(sanitizeTotalRows(this.totalRows) / sanitizePerPage(this.perPage)); return result < 1 ? 1 : result; }, // Used for watching changes to `perPage` and `numberOfPages` pageSizeNumberOfPages: function pageSizeNumberOfPages() { return { perPage: sanitizePerPage(this.perPage), totalRows: sanitizeTotalRows(this.totalRows), numberOfPages: this.numberOfPages }; } }, watch: { pageSizeNumberOfPages: function pageSizeNumberOfPages(newValue, oldValue) { if (!isUndefinedOrNull(oldValue)) { if (newValue.perPage !== oldValue.perPage && newValue.totalRows === oldValue.totalRows) { // If the page size changes, reset to page 1 this.currentPage = 1; } else if (newValue.numberOfPages !== oldValue.numberOfPages && this.currentPage > newValue.numberOfPages) { // If `numberOfPages` changes and is less than // the `currentPage` number, reset to page 1 this.currentPage = 1; } } this.localNumberOfPages = newValue.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[MODEL_PROP_NAME$f], 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; }); } }, methods: { // These methods are used by the render function onClick: function onClick(event, pageNumber) { var _this2 = this; // Dont do anything if clicking the current active page if (pageNumber === this.currentPage) { return; } var target = event.target; // Emit a user-cancelable `page-click` event var clickEvt = new BvEvent(EVENT_NAME_PAGE_CLICK, { cancelable: true, vueTarget: this, target: target }); this.$emit(clickEvt.type, clickEvt, pageNumber); if (clickEvt.defaultPrevented) { return; } // Update the `v-model` this.currentPage = pageNumber; // Emit event triggered by user interaction this.$emit(EVENT_NAME_CHANGE, this.currentPage); // Keep the current button focused if possible this.$nextTick(function () { if (isVisible(target) && _this2.$el.contains(target)) { attemptFocus(target); } else { _this2.focusCurrent(); } }); }, makePage: function makePage(pageNum) { return pageNum; }, /* istanbul ignore next */ linkProps: function linkProps() { // No props, since we render a plain button return {}; } } }); var PaginationPlugin = /*#__PURE__*/pluginFactory({ components: { BPagination: BPagination } }); // Sanitize the provided number of pages (converting to a number) var sanitizeNumberOfPages = function sanitizeNumberOfPages(value) { return mathMax(toInteger(value, 0), 1); }; // --- Props --- var _linkProps = omit(props$6, ['event', 'routerTag']); var props$1G = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$1E), _linkProps), {}, { baseUrl: makeProp(PROP_TYPE_STRING, '/'), linkGen: makeProp(PROP_TYPE_FUNCTION), // Disable auto page number detection if `true` noPageDetect: makeProp(PROP_TYPE_BOOLEAN, false), numberOfPages: makeProp(PROP_TYPE_NUMBER_STRING, 1, /* istanbul ignore next */ function (value) { var number = toInteger(value, 0); if (number < 1) { warn('Prop "number-of-pages" must be a number greater than "0"', NAME_PAGINATION_NAV); return false; } return true; }), pageGen: makeProp(PROP_TYPE_FUNCTION), // Optional array of page links pages: makeProp(PROP_TYPE_ARRAY), useRouter: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_PAGINATION_NAV); // --- Main component --- // @vue/component var BPaginationNav = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_PAGINATION_NAV, // The render function is brought in via the pagination mixin mixins: [paginationMixin], props: props$1G, 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 value = toInteger(this.value, 0); return value < 1 ? null : value; } }, 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(event, pageNumber) { var _this5 = this; // Dont do anything if clicking the current active page if (pageNumber === this.currentPage) { return; } var target = event.currentTarget || event.target; // Emit a user-cancelable `page-click` event var clickEvt = new BvEvent(EVENT_NAME_PAGE_CLICK, { cancelable: true, vueTarget: this, target: target }); this.$emit(clickEvt.type, clickEvt, pageNumber); if (clickEvt.defaultPrevented) { return; } // Update the `v-model` // Done in in requestAF() to allow browser to complete the // native browser click handling of a link requestAF(function () { _this5.currentPage = pageNumber; _this5.$emit(EVENT_NAME_CHANGE, pageNumber); }); // Emulate native link click page reloading behaviour by blurring the // paginator and returning focus to the document // Done in a `nextTick()` to ensure rendering complete this.$nextTick(function () { attemptBlur(target); }); }, getPageInfo: function getPageInfo(pageNumber) { if (!isArray(this.pages) || this.pages.length === 0 || isUndefined(this.pages[pageNumber - 1])) { var link = "".concat(this.baseUrl).concat(pageNumber); return { link: this.useRouter ? { path: link } : link, text: toString$1(pageNumber) }; } var info = this.pages[pageNumber - 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 || pageNumber) }; } else { return { link: toString$1(info), text: toString$1(pageNumber) }; } }, makePage: function makePage(pageNumber) { var pageGen = this.pageGen; var info = this.getPageInfo(pageNumber); if (hasPropFunction(pageGen)) { return pageGen(pageNumber, info); } return info.text; }, makeLink: function makeLink(pageNumber) { var linkGen = this.linkGen; var info = this.getPageInfo(pageNumber); if (hasPropFunction(linkGen)) { return linkGen(pageNumber, info); } return info.link; }, linkProps: function linkProps(pageNumber) { var props = pluckProps(_linkProps, this); var link = this.makeLink(pageNumber); 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 (_unused) {} /* 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 $router = this.$router, $route = this.$route; var guess = this.computedValue; // This section only occurs if we are client side, or server-side with `$router` if (!this.noPageDetect && !guess && (IS_BROWSER || !IS_BROWSER && $router)) { // Current route (if router available) var currentRoute = $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 = IS_BROWSER ? window.location || document.location : null; var currentLink = loc ? { path: loc.pathname, hash: loc.hash, query: parseQuery(loc.search) } : /* istanbul ignore next */ {}; // Loop through the possible pages looking for a match until found for (var pageNumber = 1; !guess && pageNumber <= this.localNumberOfPages; pageNumber++) { var to = this.makeLink(pageNumber); if ($router && (isObject(to) || this.useRouter)) { // Resolve the page via the `$router` guess = looseEqual(this.resolveRoute(to), currentRoute) ? pageNumber : null; } else if (IS_BROWSER) { // If no `$router` available (or `!this.useRouter` when `to` is a string) // we compare using parsed URIs guess = looseEqual(this.resolveLink(to), currentLink) ? pageNumber : 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 `currentPage` is `-1` when no value is specified // 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 AttachmentMap = { 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 }; // --- Props --- var props$1H = { // The minimum distance (in `px`) from the edge of the // tooltip/popover that the arrow can be positioned arrowPadding: makeProp(PROP_TYPE_NUMBER_STRING, 6), // 'scrollParent', 'viewport', 'window', or `Element` boundary: makeProp([HTMLElement, PROP_TYPE_STRING], 'scrollParent'), // Tooltip/popover will try and stay away from // boundary edge by this many pixels boundaryPadding: makeProp(PROP_TYPE_NUMBER_STRING, 5), fallbackPlacement: makeProp(PROP_TYPE_ARRAY_STRING, 'flip'), offset: makeProp(PROP_TYPE_NUMBER_STRING, 0), placement: makeProp(PROP_TYPE_STRING, 'top'), // Element that the tooltip/popover is positioned relative to target: makeProp([HTMLElement, SVGElement]) }; // --- Main component --- // @vue/component var BVPopper = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_POPPER, props: props$1H, data: function data() { return { // reactive props set by parent noFade: false, // State related data localShow: true, attachment: this.getAttachment(this.placement) }; }, computed: { /* istanbul ignore next */ templateType: function templateType() { // 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(EVENT_NAME_SHOW, function (el) { _this2.popperCreate(el); }); // Self destruct handler var handleDestroy = function handleDestroy() { _this2.$nextTick(function () { // In a `requestAF()` to release control back to application requestAF(function () { _this2.$destroy(); }); }); }; // Self destruct if parent destroyed this.$parent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy); // Self destruct after hidden this.$once(EVENT_NAME_HIDDEN, handleDestroy); }, 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); }, updated: function updated() { // Update popper if needed // TODO: Should this be a watcher on `this.popperConfig` instead? this.updatePopper(); }, beforeDestroy: function beforeDestroy() { this.destroyPopper(); }, 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[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 = toFloat(getCS(arrow).width, 0) + toFloat(this.arrowPadding, 0); switch (OffsetMap[String(placement).toUpperCase()] || 0) { /* istanbul ignore next: can't test in JSDOM */ case +1: /* istanbul ignore next: can't test in JSDOM */ return "+50%p - ".concat(arrowOffset, "px"); /* istanbul ignore next: can't test in JSDOM */ 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.destroyPopper(); // 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); }, destroyPopper: function destroyPopper() { this.$_popper && this.$_popper.destroy(); this.$_popper = null; }, updatePopper: function updatePopper() { this.$_popper && this.$_popper.scheduleUpdate(); }, popperPlacementChange: function popperPlacementChange(data) { // Callback used by popper to adjust the arrow placement this.attachment = this.getAttachment(data.placement); }, /* istanbul ignore next */ renderTemplate: function renderTemplate(h) { // Will be overridden by templates return h('div'); } }, render: function render(h) { var _this3 = this; var noFade = this.noFade; // Note: 'show' and 'fade' classes are only appled during transition return h(BVTransition, { // Transitions as soon as mounted props: { appear: true, noFade: noFade }, on: { // Events used by parent component/instance beforeEnter: function beforeEnter(el) { return _this3.$emit(EVENT_NAME_SHOW, el); }, afterEnter: function afterEnter(el) { return _this3.$emit(EVENT_NAME_SHOWN, el); }, beforeLeave: function beforeLeave(el) { return _this3.$emit(EVENT_NAME_HIDE, el); }, afterLeave: function afterLeave(el) { return _this3.$emit(EVENT_NAME_HIDDEN, el); } } }, [this.localShow ? this.renderTemplate(h) : h()]); } }); var props$1I = { // Used only by the directive versions html: makeProp(PROP_TYPE_BOOLEAN, false), // Other non-reactive (while open) props are pulled in from BVPopper id: makeProp(PROP_TYPE_STRING) }; // --- Main component --- // @vue/component var BVTooltipTemplate = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TOOLTIP_TEMPLATE, extends: BVPopper, mixins: [scopedStyleMixin], props: props$1I, 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; var variant = this.variant, attachment = this.attachment, templateType = this.templateType; return [(_ref = { // Disables pointer events to hide the tooltip when the user // hovers over its content noninteractive: !this.interactive }, _defineProperty(_ref, "b-".concat(templateType, "-").concat(variant), variant), _defineProperty(_ref, "bs-".concat(templateType, "-").concat(attachment), attachment), _ref), this.customClass]; }, templateAttributes: function templateAttributes() { var id = this.id; return _objectSpread2(_objectSpread2({}, this.$parent.$parent.$attrs), {}, { id: id, role: 'tooltip', tabindex: '-1' }, this.scopedStyleAttrs); }, templateListeners: function templateListeners() { var _this = this; // Used for hover/focus trigger listeners return { mouseenter: /* istanbul ignore next */ function mouseenter(event) { _this.$emit(EVENT_NAME_MOUSEENTER, event); }, mouseleave: /* istanbul ignore next */ function mouseleave(event) { _this.$emit(EVENT_NAME_MOUSELEAVE, event); }, focusin: /* istanbul ignore next */ function focusin(event) { _this.$emit(EVENT_NAME_FOCUSIN, event); }, focusout: /* istanbul ignore next */ function focusout(event) { _this.$emit(EVENT_NAME_FOCUSOUT, event); } }; } }, methods: { renderTemplate: function renderTemplate(h) { var title = this.title; // Title can be a scoped slot function var $title = isFunction(title) ? title({}) : title; // Directive versions only var domProps = this.html && !isFunction(title) ? { innerHTML: title } : {}; return h('div', { staticClass: 'tooltip b-tooltip', class: this.templateClasses, attrs: this.templateAttributes, on: this.templateListeners }, [h('div', { staticClass: 'arrow', ref: 'arrow' }), h('div', { staticClass: 'tooltip-inner', domProps: domProps }, [$title])]); } } }); // Modal container selector for appending tooltip/popover var MODAL_SELECTOR = '.modal-content'; // Modal `$root` hidden event var ROOT_EVENT_NAME_MODAL_HIDDEN = getRootEventName(NAME_MODAL, EVENT_NAME_HIDDEN); // Sidebar container selector for appending tooltip/popover var SIDEBAR_SELECTOR = '.b-sidebar'; // For finding the container to append to var CONTAINER_SELECTOR = [MODAL_SELECTOR, SIDEBAR_SELECTOR].join(', '); // For dropdown sniffing var DROPDOWN_CLASS = 'dropdown'; var DROPDOWN_OPEN_SELECTOR = '.dropdown-menu.show'; // Data attribute to temporary store the `title` attribute's value var DATA_TITLE_ATTR = 'data-original-title'; // 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 }; // --- Main component --- // @vue/component var BVTooltip = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TOOLTIP_HELPER, mixins: [listenOnRootMixin], data: function data() { return _objectSpread2(_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[COMPONENT_UID_KEY], "__"); }, computedDelay: function computedDelay() { // Normalizes delay into object form var delay = { show: 0, hide: 0 }; if (isPlainObject(this.delay)) { delay.show = mathMax(toInteger(this.delay.show, 0), 0); delay.hide = mathMax(toInteger(this.delay.hide, 0), 0); } else if (isNumber(this.delay) || isString(this.delay)) { delay.show = delay.hide = mathMax(toInteger(this.delay, 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(identity).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() { var title = this.title, content = this.content, variant = this.variant, customClass = this.customClass, noFade = this.noFade, interactive = this.interactive; return { title: title, content: content, variant: variant, customClass: customClass, noFade: noFade, interactive: 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(); }, title: function title(newValue, oldValue) { // Make sure to hide the tooltip when the title is set empty if (newValue !== oldValue && !newValue) { this.hide(); } }, disabled: function disabled(newValue) { if (newValue) { this.disable(); } else { 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_EVENT_NAME_BEFORE_DESTROY, function () { _this2.$nextTick(function () { // In a `requestAF()` to release control back to application requestAF(function () { _this2.$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(isString(_this2.target) ? "Unable to find target element by ID \"#".concat(_this2.target, "\" in document.") : 'The provided target is no valid HTML element.', _this2.templateType); } }); }, /* istanbul ignore next */ updated: function updated() { // Usually called when the slots/data changes this.$nextTick(this.handleTemplateUpdate); }, /* istanbul ignore next */ deactivated: function deactivated() { // In a keepalive that has been deactivated, so hide // the tooltip/popover if it is showing this.forceHide(); }, beforeDestroy: function beforeDestroy() { // Remove all handler/listeners this.unListen(); this.setWhileOpenListeners(false); // Clear any timeouts/intervals this.clearHoverTimeout(); this.clearVisibilityInterval(); // Destroy the template this.destroyTemplate(); // Remove any other private properties created during create this.$_noop = null; }, 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 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 if (titleUpdated && this.localShow) { 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: toInteger(this.offset, 0), arrowPadding: toInteger(this.arrowPadding, 0), boundaryPadding: toInteger(this.boundaryPadding, 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(EVENT_NAME_SHOW, this.onTemplateShow); // When the template has completed showing $tip.$once(EVENT_NAME_SHOWN, this.onTemplateShown); // When the template has started to hide $tip.$once(EVENT_NAME_HIDE, this.onTemplateHide); // When the template has completed hiding $tip.$once(EVENT_NAME_HIDDEN, this.onTemplateHidden); // When the template gets destroyed for any reason $tip.$once(HOOK_EVENT_NAME_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(EVENT_NAME_FOCUSIN, this.handleEvent); $tip.$on(EVENT_NAME_FOCUSOUT, this.handleEvent); $tip.$on(EVENT_NAME_MOUSEENTER, this.handleEvent); $tip.$on(EVENT_NAME_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.$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(EVENT_NAME_SHOW, { cancelable: true }); this.emitEvent(showEvt); // Don't show if event cancelled /* istanbul ignore if */ if (showEvt.defaultPrevented) { // Destroy the template (if for some reason it was created) this.destroyTemplate(); 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(); /* istanbul ignore if */ if (!tip || !this.localShow) { this.restoreTitle(); return; } // Emit cancelable BvEvent 'hide' // We disable cancelling if `force` is true var hideEvt = this.buildEvent(EVENT_NAME_HIDE, { cancelable: !force }); this.emitEvent(hideEvt); /* istanbul ignore if: ignore for now */ if (hideEvt.defaultPrevented) { // Don't hide if event cancelled 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` event 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(EVENT_NAME_ENABLED)); }, disable: function disable() { this.$_enabled = false; // Create a non-cancelable BvEvent this.emitEvent(this.buildEvent(EVENT_NAME_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 = ''; /* istanbul ignore next: occasional Node 10 coverage error */ if (prevHoverState === 'out') { this.leave(null); } // Emit a non-cancelable BvEvent 'shown' this.emitEvent(this.buildEvent(EVENT_NAME_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(EVENT_NAME_HIDDEN)); }, // --- Helper methods --- getTarget: function getTarget() { var target = this.target; if (isString(target)) { target = getById(target.replace(/^#/, '')); } else if (isFunction(target)) { target = target(); } else if (target) { target = target.$el || target; } 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, If we // are in a sidebar, we append to the sidebar, else append // to 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(CONTAINER_SELECTOR, target) || body : /*istanbul ignore next */ isString(container) ? /*istanbul ignore next */ getById(container.replace(/^#/, '')) || body : /*istanbul ignore next */ 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() { clearTimeout(this.$_hoverTimeout); this.$_hoverTimeout = null; }, clearVisibilityInterval: function clearVisibilityInterval() { 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, // remove it and store it on a data attribute var target = this.getTarget(); if (hasAttr(target, 'title')) { // Get `title` attribute value and remove it from target var title = getAttr(target, 'title'); setAttr(target, 'title', ''); // Only set the data attribute when the value is truthy if (title) { setAttr(target, DATA_TITLE_ATTR, title); } } }, restoreTitle: function restoreTitle() { // If the target had a `title` attribute, // restore it and remove the data attribute var target = this.getTarget(); if (hasAttr(target, DATA_TITLE_ATTR)) { // Get data attribute value and remove it from target var title = getAttr(target, DATA_TITLE_ATTR); removeAttr(target, DATA_TITLE_ATTR); // Only restore the `title` attribute when the value is truthy if (title) { setAttr(target, 'title', 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(bvEvent) { var type = bvEvent.type; this.emitOnRoot(getRootEventName(this.templateType, type), bvEvent); this.$emit(type, bvEvent); }, // --- 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); }, /* istanbul ignore next */ unListen: function unListen() { 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 (event) { target && eventOff(target, event, _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](getRootActionEventName(type, EVENT_NAME_HIDE), this.doHide); $root[method](getRootActionEventName(type, EVENT_NAME_SHOW), this.doShow); $root[method](getRootActionEventName(type, EVENT_NAME_DISABLE), this.doDisable); $root[method](getRootActionEventName(type, EVENT_NAME_ENABLE), 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'](ROOT_EVENT_NAME_MODAL_HIDDEN, this.forceHide); } }, /* istanbul ignore next: JSDOM doesn't support `ontouchstart` */ setOnTouchStartListener: function setOnTouchStartListener(on) { 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'](EVENT_NAME_SHOWN, this.forceHide); } }, // --- Event handlers --- handleEvent: function handleEvent(event) { // 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 = event.type; var triggers = this.computedTriggers; if (type === 'click' && arrayIncludes(triggers, 'click')) { this.click(event); } else if (type === 'mouseenter' && arrayIncludes(triggers, 'hover')) { // `mouseenter` is a non-bubbling event this.enter(event); } else if (type === 'focusin' && arrayIncludes(triggers, 'focus')) { // `focusin` is a bubbling event // `event` includes `relatedTarget` (element losing focus) this.enter(event); } 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(); // `eventTarget` is the element which is losing focus/hover and var eventTarget = event.target; // `relatedTarget` is the element gaining focus/hover var relatedTarget = event.relatedTarget; /* istanbul ignore next */ if ( // From tip to target tip && contains(tip, eventTarget) && contains(target, relatedTarget) || // From target to tip tip && contains(target, eventTarget) && contains(tip, relatedTarget) || // Within tip tip && contains(tip, eventTarget) && contains(tip, relatedTarget) || // Within target contains(target, eventTarget) && contains(target, relatedTarget)) { // If focus/hover moves within `tip` and `target`, don't trigger a leave return; } // Otherwise trigger a leave this.leave(event); } }, 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(); } }, /*istanbul ignore next: ignore for now */ 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(); } }, /*istanbul ignore next: ignore for now */ 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(event) { if (!this.$_enabled || this.dropdownOpen()) { /* istanbul ignore next */ return; } // Get around a WebKit bug where `click` does not trigger focus events // On most browsers, `click` triggers a `focusin`/`focus` event first // Needed so that trigger 'click blur' works on iOS // https://github.com/bootstrap-vue/bootstrap-vue/issues/5099 // We use `currentTarget` rather than `target` to trigger on the // element, not the inner content attemptFocus(event.currentTarget); this.activeTrigger.click = !this.activeTrigger.click; if (this.isWithActiveTrigger) { this.enter(null); } else { /* istanbul ignore next */ this.leave(null); } }, /* istanbul ignore next */ toggle: function toggle() { // 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 event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; // Opening trigger handler // Note: Click events are sent with event === null if (event) { this.activeTrigger[event.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 event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; // Closing trigger handler // Note: Click events are sent with event === null if (event) { this.activeTrigger[event.type === 'focusout' ? 'focus' : 'hover'] = false; /* istanbul ignore next */ if (event.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 _makePropsConfigurabl, _watch$f; var MODEL_PROP_NAME_ENABLED = 'disabled'; var MODEL_EVENT_NAME_ENABLED = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_ENABLED; var MODEL_PROP_NAME_SHOW$1 = 'show'; var MODEL_EVENT_NAME_SHOW$1 = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_SHOW$1; // --- Props --- var props$1J = makePropsConfigurable((_makePropsConfigurabl = { // String: scrollParent, window, or viewport // Element: element reference // Object: Vue component boundary: makeProp([HTMLElement, PROP_TYPE_OBJECT, PROP_TYPE_STRING], 'scrollParent'), boundaryPadding: makeProp(PROP_TYPE_NUMBER_STRING, 50), // String: HTML ID of container, if null body is used (default) // HTMLElement: element reference reference // Object: Vue Component container: makeProp([HTMLElement, PROP_TYPE_OBJECT, PROP_TYPE_STRING]), customClass: makeProp(PROP_TYPE_STRING), delay: makeProp(PROP_TYPE_NUMBER_OBJECT_STRING, 50) }, _defineProperty(_makePropsConfigurabl, MODEL_PROP_NAME_ENABLED, makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_makePropsConfigurabl, "fallbackPlacement", makeProp(PROP_TYPE_ARRAY_STRING, 'flip')), _defineProperty(_makePropsConfigurabl, "id", makeProp(PROP_TYPE_STRING)), _defineProperty(_makePropsConfigurabl, "noFade", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_makePropsConfigurabl, "noninteractive", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_makePropsConfigurabl, "offset", makeProp(PROP_TYPE_NUMBER_STRING, 0)), _defineProperty(_makePropsConfigurabl, "placement", makeProp(PROP_TYPE_STRING, 'top')), _defineProperty(_makePropsConfigurabl, MODEL_PROP_NAME_SHOW$1, makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_makePropsConfigurabl, "target", makeProp([HTMLElement, SVGElement, PROP_TYPE_FUNCTION, PROP_TYPE_OBJECT, PROP_TYPE_STRING], undefined, true)), _defineProperty(_makePropsConfigurabl, "title", makeProp(PROP_TYPE_STRING)), _defineProperty(_makePropsConfigurabl, "triggers", makeProp(PROP_TYPE_ARRAY_STRING, 'hover focus')), _defineProperty(_makePropsConfigurabl, "variant", makeProp(PROP_TYPE_STRING)), _makePropsConfigurabl), NAME_TOOLTIP); // --- Main component --- // @vue/component var BTooltip = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TOOLTIP, mixins: [normalizeSlotMixin], inheritAttrs: false, props: props$1J, data: function data() { return { localShow: this[MODEL_PROP_NAME_SHOW$1], localTitle: '', localContent: '' }; }, computed: { // Data that will be passed to the template and popper templateData: function templateData() { return _objectSpread2({ title: this.localTitle, content: this.localContent, interactive: !this.noninteractive }, pick(this.$props, ['boundary', 'boundaryPadding', 'container', 'customClass', 'delay', 'fallbackPlacement', 'id', 'noFade', 'offset', 'placement', 'target', 'target', 'triggers', 'variant', MODEL_PROP_NAME_ENABLED])); }, // Used to watch for changes to the title and content props templateTitleContent: function templateTitleContent() { var title = this.title, content = this.content; return { title: title, content: content }; } }, watch: (_watch$f = {}, _defineProperty(_watch$f, MODEL_PROP_NAME_SHOW$1, function (newValue, oldValue) { if (newValue !== oldValue && newValue !== this.localShow && this.$_toolpop) { if (newValue) { this.$_toolpop.show(); } else { // We use `forceHide()` to override any active triggers this.$_toolpop.forceHide(); } } }), _defineProperty(_watch$f, MODEL_PROP_NAME_ENABLED, function (newValue) { if (newValue) { this.doDisable(); } else { this.doEnable(); } }), _defineProperty(_watch$f, "localShow", function localShow(newValue) { // TODO: May need to be done in a `$nextTick()` this.$emit(MODEL_EVENT_NAME_SHOW$1, newValue); }), _defineProperty(_watch$f, "templateData", function templateData() { var _this = this; this.$nextTick(function () { if (_this.$_toolpop) { _this.$_toolpop.updateData(_this.templateData); } }); }), _defineProperty(_watch$f, "templateTitleContent", function templateTitleContent() { this.$nextTick(this.updateContent); }), _watch$f), created: function created() { // Create private non-reactive props this.$_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(EVENT_NAME_OPEN, this.doOpen); this.$off(EVENT_NAME_CLOSE, this.doClose); this.$off(EVENT_NAME_DISABLE, this.doDisable); this.$off(EVENT_NAME_ENABLE, this.doEnable); // Destroy the tip instance if (this.$_toolpop) { this.$_toolpop.$destroy(); this.$_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.$_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(EVENT_NAME_SHOW, _this2.onShow); $toolpop.$on(EVENT_NAME_SHOWN, _this2.onShown); $toolpop.$on(EVENT_NAME_HIDE, _this2.onHide); $toolpop.$on(EVENT_NAME_HIDDEN, _this2.onHidden); $toolpop.$on(EVENT_NAME_DISABLED, _this2.onDisabled); $toolpop.$on(EVENT_NAME_ENABLED, _this2.onEnabled); // Initially disabled? if (_this2[MODEL_PROP_NAME_ENABLED]) { // Initially disabled _this2.doDisable(); } // Listen to open signals from others _this2.$on(EVENT_NAME_OPEN, _this2.doOpen); // Listen to close signals from others _this2.$on(EVENT_NAME_CLOSE, _this2.doClose); // Listen to disable signals from others _this2.$on(EVENT_NAME_DISABLE, _this2.doDisable); // Listen to enable signals from others _this2.$on(EVENT_NAME_ENABLE, _this2.doEnable); // Initially show tooltip? if (_this2.localShow) { $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.normalizeSlot() || this.title); }, // Helper methods for `updateContent()` setTitle: function setTitle(value) { value = isUndefinedOrNull(value) ? '' : value; // We only update the value if it has changed if (this.localTitle !== value) { this.localTitle = value; } }, setContent: function setContent(value) { value = isUndefinedOrNull(value) ? '' : value; // We only update the value if it has changed if (this.localContent !== value) { this.localContent = value; } }, // --- Template event handlers --- onShow: function onShow(bvEvent) { // Placeholder this.$emit(EVENT_NAME_SHOW, bvEvent); if (bvEvent) { this.localShow = !bvEvent.defaultPrevented; } }, onShown: function onShown(bvEvent) { // Tip is now showing this.localShow = true; this.$emit(EVENT_NAME_SHOWN, bvEvent); }, onHide: function onHide(bvEvent) { this.$emit(EVENT_NAME_HIDE, bvEvent); }, onHidden: function onHidden(bvEvent) { // Tip is no longer showing this.$emit(EVENT_NAME_HIDDEN, bvEvent); this.localShow = false; }, onDisabled: function onDisabled(bvEvent) { // Prevent possible endless loop if user mistakenly // fires `disabled` instead of `disable` if (bvEvent && bvEvent.type === EVENT_NAME_DISABLED) { this.$emit(MODEL_EVENT_NAME_ENABLED, true); this.$emit(EVENT_NAME_DISABLED, bvEvent); } }, onEnabled: function onEnabled(bvEvent) { // Prevent possible endless loop if user mistakenly // fires `enabled` instead of `enable` if (bvEvent && bvEvent.type === EVENT_NAME_ENABLED) { this.$emit(MODEL_EVENT_NAME_ENABLED, false); this.$emit(EVENT_NAME_ENABLED, bvEvent); } }, // --- Local event listeners --- doOpen: function doOpen() { !this.localShow && this.$_toolpop && this.$_toolpop.show(); }, doClose: function doClose() { this.localShow && this.$_toolpop && this.$_toolpop.hide(); }, doDisable: function doDisable() { this.$_toolpop && this.$_toolpop.disable(); }, doEnable: function doEnable() { this.$_toolpop && this.$_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 BVPopoverTemplate = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_POPOVER_TEMPLATE, extends: BVTooltipTemplate, computed: { templateType: function templateType() { return 'popover'; } }, methods: { renderTemplate: function renderTemplate(h) { var title = this.title, content = this.content; // Title and content could be a scoped slot function var $title = isFunction(title) ? title({}) : title; var $content = isFunction(content) ? content({}) : content; // Directive usage only var titleDomProps = this.html && !isFunction(title) ? { innerHTML: title } : {}; var contentDomProps = this.html && !isFunction(content) ? { innerHTML: content } : {}; return h('div', { staticClass: 'popover b-popover', class: this.templateClasses, attrs: this.templateAttributes, on: this.templateListeners }, [h('div', { staticClass: 'arrow', ref: 'arrow' }), isUndefinedOrNull($title) || $title === '' ? /* istanbul ignore next */ h() : h('h3', { staticClass: 'popover-header', domProps: titleDomProps }, [$title]), isUndefinedOrNull($content) || $content === '' ? /* istanbul ignore next */ h() : h('div', { staticClass: 'popover-body', domProps: contentDomProps }, [$content])]); } } }); // Popover "Class" (Built as a renderless Vue instance) var BVPopover = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_POPOVER_HELPER, extends: BVTooltip, computed: { // Overwrites BVTooltip templateType: function templateType() { return 'popover'; } }, methods: { getTemplate: function getTemplate() { // Overwrites BVTooltip return BVPopoverTemplate; } } }); var props$1K = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$1J), {}, { content: makeProp(PROP_TYPE_STRING), placement: makeProp(PROP_TYPE_STRING, 'right'), triggers: makeProp(PROP_TYPE_ARRAY_STRING, EVENT_NAME_CLICK) })), NAME_POPOVER); // --- Main component --- // @vue/component var BPopover = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_POPOVER, extends: BTooltip, inheritAttrs: false, props: props$1K, 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.normalizeSlot() || this.content); this.setTitle(this.normalizeSlot(SLOT_NAME_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 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_POPOVER, 'delay', 50), boundary: String(getComponentConfig(NAME_POPOVER, 'boundary', 'scrollParent')), boundaryPadding: toInteger(getComponentConfig(NAME_POPOVER, 'boundaryPadding', 5), 0), variant: getComponentConfig(NAME_POPOVER, 'variant'), customClass: getComponentConfig(NAME_POPOVER, '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(_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: toInteger(config.delay, 0), hide: toInteger(config.delay, 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 = toInteger(mod.slice(1), 0); config.delay.show = delay; config.delay.hide = delay; } else if (delayShowRE.test(mod)) { // Delay show value config.delay.show = toInteger(mod.slice(2), 0); } else if (delayHideRE.test(mod)) { // Delay hide value config.delay.hide = toInteger(mod.slice(2), 0); } else if (offsetRE.test(mod)) { // Offset value, negative allowed config.offset = toInteger(mod.slice(1), 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 (!IS_BROWSER) { /* 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(EVENT_NAME_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]) ? /* istanbul ignore next */ 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 props$1L = makePropsConfigurable({ animated: makeProp(PROP_TYPE_BOOLEAN, null), label: makeProp(PROP_TYPE_STRING), labelHtml: makeProp(PROP_TYPE_STRING), max: makeProp(PROP_TYPE_NUMBER_STRING, null), precision: makeProp(PROP_TYPE_NUMBER_STRING, null), showProgress: makeProp(PROP_TYPE_BOOLEAN, null), showValue: makeProp(PROP_TYPE_BOOLEAN, null), striped: makeProp(PROP_TYPE_BOOLEAN, null), value: makeProp(PROP_TYPE_NUMBER_STRING, 0), variant: makeProp(PROP_TYPE_STRING) }, NAME_PROGRESS_BAR); // --- Main component --- // @vue/component var BProgressBar = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_PROGRESS_BAR, mixins: [normalizeSlotMixin], inject: { bvProgress: { default: /* istanbul ignore next */ function _default() { return {}; } } }, props: props$1L, computed: { progressBarClasses: function progressBarClasses() { var computedAnimated = this.computedAnimated, computedVariant = this.computedVariant; return [computedVariant ? "bg-".concat(computedVariant) : '', this.computedStriped || computedAnimated ? 'progress-bar-striped' : '', 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 // Default to `100` for invalid values (`-x`, `0`, `NaN`) var max = toFloat(this.max) || toFloat(this.bvProgress.max, 0); return max > 0 ? max : 100; }, computedPrecision: function computedPrecision() { // Prefer our precision over parent setting // Default to `0` for invalid values (`-x`, `NaN`) return mathMax(toInteger(this.precision, toInteger(this.bvProgress.precision, 0)), 0); }, computedProgress: function computedProgress() { var precision = this.computedPrecision; var p = mathPow(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 label = this.label, labelHtml = this.labelHtml, computedValue = this.computedValue, computedPrecision = this.computedPrecision; var $children; var domProps = {}; if (this.hasNormalizedSlot()) { $children = this.normalizeSlot(); } else if (label || labelHtml) { domProps = htmlOrText(labelHtml, label); } else if (this.computedShowProgress) { $children = this.computedProgress; } else if (this.computedShowValue) { $children = toFixed(computedValue, 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(computedValue, computedPrecision) }, domProps: domProps }, $children); } }); var progressBarProps = omit(props$1L, ['label', 'labelHtml']); var props$1M = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, progressBarProps), {}, { animated: makeProp(PROP_TYPE_BOOLEAN, false), height: makeProp(PROP_TYPE_STRING), max: makeProp(PROP_TYPE_NUMBER_STRING, 100), precision: makeProp(PROP_TYPE_NUMBER_STRING, 0), showProgress: makeProp(PROP_TYPE_BOOLEAN, false), showValue: makeProp(PROP_TYPE_BOOLEAN, false), striped: makeProp(PROP_TYPE_BOOLEAN, false) })), NAME_PROGRESS); // --- Main component --- // @vue/component var BProgress = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_PROGRESS, mixins: [normalizeSlotMixin], provide: function provide() { return { bvProgress: this }; }, props: props$1M, computed: { progressHeight: function progressHeight() { return { height: this.height || null }; } }, render: function render(h) { var $childNodes = this.normalizeSlot(); if (!$childNodes) { $childNodes = h(BProgressBar, { props: pluckProps(progressBarProps, this.$props) }); } return h('div', { staticClass: 'progress', style: this.progressHeight }, [$childNodes]); } }); var ProgressPlugin = /*#__PURE__*/pluginFactory({ components: { BProgress: BProgress, BProgressBar: BProgressBar } }); var _watch$g; var CLASS_NAME$3 = 'b-sidebar'; var ROOT_ACTION_EVENT_NAME_REQUEST_STATE$2 = getRootActionEventName(NAME_COLLAPSE, 'request-state'); var ROOT_ACTION_EVENT_NAME_TOGGLE$2 = getRootActionEventName(NAME_COLLAPSE, 'toggle'); var ROOT_EVENT_NAME_STATE$3 = getRootEventName(NAME_COLLAPSE, 'state'); var ROOT_EVENT_NAME_SYNC_STATE$3 = getRootEventName(NAME_COLLAPSE, 'sync-state'); var _makeModelMixin$h = makeModelMixin('visible', { type: PROP_TYPE_BOOLEAN, defaultValue: false, event: EVENT_NAME_CHANGE }), modelMixin$g = _makeModelMixin$h.mixin, modelProps$g = _makeModelMixin$h.props, MODEL_PROP_NAME$g = _makeModelMixin$h.prop, MODEL_EVENT_NAME$g = _makeModelMixin$h.event; // --- Props --- var props$1N = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$g), {}, { ariaLabel: makeProp(PROP_TYPE_STRING), ariaLabelledby: makeProp(PROP_TYPE_STRING), // If `true`, shows a basic backdrop backdrop: makeProp(PROP_TYPE_BOOLEAN, false), backdropVariant: makeProp(PROP_TYPE_STRING, 'dark'), bgVariant: makeProp(PROP_TYPE_STRING, 'light'), bodyClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), // `aria-label` for close button closeLabel: makeProp(PROP_TYPE_STRING), footerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), headerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), lazy: makeProp(PROP_TYPE_BOOLEAN, false), noCloseOnBackdrop: makeProp(PROP_TYPE_BOOLEAN, false), noCloseOnEsc: makeProp(PROP_TYPE_BOOLEAN, false), noCloseOnRouteChange: makeProp(PROP_TYPE_BOOLEAN, false), noEnforceFocus: makeProp(PROP_TYPE_BOOLEAN, false), noHeader: makeProp(PROP_TYPE_BOOLEAN, false), noHeaderClose: makeProp(PROP_TYPE_BOOLEAN, false), noSlide: makeProp(PROP_TYPE_BOOLEAN, false), right: makeProp(PROP_TYPE_BOOLEAN, false), shadow: makeProp(PROP_TYPE_BOOLEAN_STRING, false), sidebarClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), tag: makeProp(PROP_TYPE_STRING, 'div'), textVariant: makeProp(PROP_TYPE_STRING, 'dark'), title: makeProp(PROP_TYPE_STRING), width: makeProp(PROP_TYPE_STRING), zIndex: makeProp(PROP_TYPE_NUMBER_STRING) })), NAME_SIDEBAR); // --- Render methods --- var renderHeaderTitle = function renderHeaderTitle(h, ctx) { // Render a empty `<span>` when to title was provided var title = ctx.normalizeSlot(SLOT_NAME_TITLE, ctx.slotScope) || ctx.title; if (!title) { return h('span'); } return h('strong', { attrs: { id: ctx.safeId('__title__') } }, [title]); }; var renderHeaderClose = function renderHeaderClose(h, ctx) { if (ctx.noHeaderClose) { return h(); } var closeLabel = ctx.closeLabel, textVariant = ctx.textVariant, hide = ctx.hide; return h(BButtonClose, { props: { ariaLabel: closeLabel, textVariant: textVariant }, on: { click: hide }, ref: 'close-button' }, [ctx.normalizeSlot(SLOT_NAME_HEADER_CLOSE) || h(BIconX)]); }; var renderHeader = function renderHeader(h, ctx) { if (ctx.noHeader) { return h(); } var $content = ctx.normalizeSlot(SLOT_NAME_HEADER, ctx.slotScope); if (!$content) { var $title = renderHeaderTitle(h, ctx); var $close = renderHeaderClose(h, ctx); $content = ctx.right ? [$close, $title] : [$title, $close]; } return h('header', { staticClass: "".concat(CLASS_NAME$3, "-header"), class: ctx.headerClass, key: 'header' }, $content); }; var renderBody = function renderBody(h, ctx) { return h('div', { staticClass: "".concat(CLASS_NAME$3, "-body"), class: ctx.bodyClass, key: 'body' }, [ctx.normalizeSlot(SLOT_NAME_DEFAULT, ctx.slotScope)]); }; var renderFooter = function renderFooter(h, ctx) { var $footer = ctx.normalizeSlot(SLOT_NAME_FOOTER, ctx.slotScope); if (!$footer) { return h(); } return h('footer', { staticClass: "".concat(CLASS_NAME$3, "-footer"), class: ctx.footerClass, key: 'footer' }, [$footer]); }; var renderContent = function renderContent(h, ctx) { // We render the header even if `lazy` is enabled as it // acts as the accessible label for the sidebar var $header = renderHeader(h, ctx); if (ctx.lazy && !ctx.isOpen) { return $header; } return [$header, renderBody(h, ctx), renderFooter(h, ctx)]; }; var renderBackdrop = function renderBackdrop(h, ctx) { if (!ctx.backdrop) { return h(); } var backdropVariant = ctx.backdropVariant; return h('div', { directives: [{ name: 'show', value: ctx.localShow }], staticClass: 'b-sidebar-backdrop', class: _defineProperty({}, "bg-".concat(backdropVariant), backdropVariant), on: { click: ctx.onBackdropClick } }); }; // --- Main component --- // @vue/component var BSidebar = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SIDEBAR, mixins: [attrsMixin, idMixin, modelMixin$g, listenOnRootMixin, normalizeSlotMixin], inheritAttrs: false, props: props$1N, data: function data() { var visible = !!this[MODEL_PROP_NAME$g]; return { // Internal `v-model` state localShow: visible, // For lazy render triggering isOpen: visible }; }, computed: { transitionProps: function transitionProps() { return this.noSlide ? /* istanbul ignore next */ { css: true } : { css: true, enterClass: '', enterActiveClass: 'slide', enterToClass: 'show', leaveClass: 'show', leaveActiveClass: 'slide', leaveToClass: '' }; }, slotScope: function slotScope() { var hide = this.hide, right = this.right, visible = this.localShow; return { hide: hide, right: right, visible: visible }; }, hasTitle: function hasTitle() { var $scopedSlots = this.$scopedSlots, $slots = this.$slots; return !this.noHeader && !this.hasNormalizedSlot(SLOT_NAME_HEADER) && !!(this.normalizeSlot(SLOT_NAME_TITLE, this.slotScope, $scopedSlots, $slots) || this.title); }, titleId: function titleId() { return this.hasTitle ? this.safeId('__title__') : null; }, computedAttrs: function computedAttrs() { return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { id: this.safeId(), tabindex: '-1', role: 'dialog', 'aria-modal': this.backdrop ? 'true' : 'false', 'aria-hidden': this.localShow ? null : 'true', 'aria-label': this.ariaLabel || null, 'aria-labelledby': this.ariaLabelledby || this.titleId || null }); } }, watch: (_watch$g = {}, _defineProperty(_watch$g, MODEL_PROP_NAME$g, function (newValue, oldValue) { if (newValue !== oldValue) { this.localShow = newValue; } }), _defineProperty(_watch$g, "localShow", function localShow(newValue, oldValue) { if (newValue !== oldValue) { this.emitState(newValue); this.$emit(MODEL_EVENT_NAME$g, newValue); } }), _defineProperty(_watch$g, "$route", function $route() { var newValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var oldValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (!this.noCloseOnRouteChange && newValue.fullPath !== oldValue.fullPath) { this.hide(); } }), _watch$g), created: function created() { // Define non-reactive properties this.$_returnFocusEl = null; }, mounted: function mounted() { var _this = this; // Add `$root` listeners this.listenOnRoot(ROOT_ACTION_EVENT_NAME_TOGGLE$2, this.handleToggle); this.listenOnRoot(ROOT_ACTION_EVENT_NAME_REQUEST_STATE$2, this.handleSync); // Send out a gratuitous state event to ensure toggle button is synced this.$nextTick(function () { _this.emitState(_this.localShow); }); }, /* istanbul ignore next */ activated: function activated() { this.emitSync(); }, beforeDestroy: function beforeDestroy() { this.localShow = false; this.$_returnFocusEl = null; }, methods: { hide: function hide() { this.localShow = false; }, emitState: function emitState() { var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.localShow; this.emitOnRoot(ROOT_EVENT_NAME_STATE$3, this.safeId(), state); }, emitSync: function emitSync() { var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.localShow; this.emitOnRoot(ROOT_EVENT_NAME_SYNC_STATE$3, this.safeId(), state); }, handleToggle: function handleToggle(id) { // Note `safeId()` can be null until after mount if (id && id === this.safeId()) { this.localShow = !this.localShow; } }, handleSync: function handleSync(id) { var _this2 = this; // Note `safeId()` can be null until after mount if (id && id === this.safeId()) { this.$nextTick(function () { _this2.emitSync(_this2.localShow); }); } }, onKeydown: function onKeydown(event) { var keyCode = event.keyCode; if (!this.noCloseOnEsc && keyCode === CODE_ESC && this.localShow) { this.hide(); } }, onBackdropClick: function onBackdropClick() { if (this.localShow && !this.noCloseOnBackdrop) { this.hide(); } }, /* istanbul ignore next */ onTopTrapFocus: function onTopTrapFocus() { var tabables = getTabables(this.$refs.content); this.enforceFocus(tabables.reverse()[0]); }, /* istanbul ignore next */ onBottomTrapFocus: function onBottomTrapFocus() { var tabables = getTabables(this.$refs.content); this.enforceFocus(tabables[0]); }, onBeforeEnter: function onBeforeEnter() { // Returning focus to `document.body` may cause unwanted scrolls, // so we exclude setting focus on body this.$_returnFocusEl = getActiveElement(IS_BROWSER ? [document.body] : []); // Trigger lazy render this.isOpen = true; }, onAfterEnter: function onAfterEnter(el) { if (!contains(el, getActiveElement())) { this.enforceFocus(el); } this.$emit(EVENT_NAME_SHOWN); }, onAfterLeave: function onAfterLeave() { this.enforceFocus(this.$_returnFocusEl); this.$_returnFocusEl = null; // Trigger lazy render this.isOpen = false; this.$emit(EVENT_NAME_HIDDEN); }, enforceFocus: function enforceFocus(el) { if (!this.noEnforceFocus) { attemptFocus(el); } } }, render: function render(h) { var _ref; var bgVariant = this.bgVariant, width = this.width, textVariant = this.textVariant, localShow = this.localShow; var shadow = this.shadow === '' ? true : this.shadow; var $sidebar = h(this.tag, { staticClass: CLASS_NAME$3, class: [(_ref = { shadow: shadow === true }, _defineProperty(_ref, "shadow-".concat(shadow), shadow && shadow !== true), _defineProperty(_ref, "".concat(CLASS_NAME$3, "-right"), this.right), _defineProperty(_ref, "bg-".concat(bgVariant), bgVariant), _defineProperty(_ref, "text-".concat(textVariant), textVariant), _ref), this.sidebarClass], style: { width: width }, attrs: this.computedAttrs, directives: [{ name: 'show', value: localShow }], ref: 'content' }, [renderContent(h, this)]); $sidebar = h('transition', { props: this.transitionProps, on: { beforeEnter: this.onBeforeEnter, afterEnter: this.onAfterEnter, afterLeave: this.onAfterLeave } }, [$sidebar]); var $backdrop = h(BVTransition, { props: { noFade: this.noSlide } }, [renderBackdrop(h, this)]); var $tabTrapTop = h(); var $tabTrapBottom = h(); if (this.backdrop && localShow) { $tabTrapTop = h('div', { attrs: { tabindex: '0' }, on: { focus: this.onTopTrapFocus } }); $tabTrapBottom = h('div', { attrs: { tabindex: '0' }, on: { focus: this.onBottomTrapFocus } }); } return h('div', { staticClass: 'b-sidebar-outer', style: { zIndex: this.zIndex }, attrs: { tabindex: '-1' }, on: { keydown: this.onKeydown } }, [$tabTrapTop, $sidebar, $tabTrapBottom, $backdrop]); } }); var SidebarPlugin = /*#__PURE__*/pluginFactory({ components: { BSidebar: BSidebar }, plugins: { VBTogglePlugin: VBTogglePlugin } }); var props$1O = makePropsConfigurable({ animation: makeProp(PROP_TYPE_STRING, 'wave'), height: makeProp(PROP_TYPE_STRING), size: makeProp(PROP_TYPE_STRING), type: makeProp(PROP_TYPE_STRING, 'text'), variant: makeProp(PROP_TYPE_STRING), width: makeProp(PROP_TYPE_STRING) }, NAME_SKELETON); // --- Main component --- // @vue/component var BSkeleton = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SKELETON, functional: true, props: props$1O, render: function render(h, _ref) { var _class; var data = _ref.data, props = _ref.props; var size = props.size, animation = props.animation, variant = props.variant; return h('div', a(data, { staticClass: 'b-skeleton', style: { width: size || props.width, height: size || props.height }, class: (_class = {}, _defineProperty(_class, "b-skeleton-".concat(props.type), true), _defineProperty(_class, "b-skeleton-animate-".concat(animation), animation), _defineProperty(_class, "bg-".concat(variant), variant), _class) })); } }); var props$1P = makePropsConfigurable(omit(props$4, ['content', 'stacked']), NAME_ICONSTACK); // --- Main component --- var props$1Q = makePropsConfigurable({ animation: makeProp(PROP_TYPE_STRING, 'wave'), icon: makeProp(PROP_TYPE_STRING), iconProps: makeProp(PROP_TYPE_OBJECT, {}) }, NAME_SKELETON_ICON); // --- Main component --- // @vue/component var BSkeletonIcon = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SKELETON_ICON, functional: true, props: props$1Q, render: function render(h, _ref) { var props = _ref.props; var icon = props.icon, animation = props.animation; var $icon = h(BIcon, { staticClass: 'b-skeleton-icon', props: _objectSpread2(_objectSpread2({}, props.iconProps), {}, { icon: icon }) }); return h('div', { staticClass: 'b-skeleton-icon-wrapper position-relative d-inline-block overflow-hidden', class: _defineProperty({}, "b-skeleton-animate-".concat(animation), animation) }, [$icon]); } }); var props$1R = makePropsConfigurable({ animation: makeProp(PROP_TYPE_STRING), aspect: makeProp(PROP_TYPE_STRING, '16:9'), cardImg: makeProp(PROP_TYPE_STRING), height: makeProp(PROP_TYPE_STRING), noAspect: makeProp(PROP_TYPE_BOOLEAN, false), variant: makeProp(PROP_TYPE_STRING), width: makeProp(PROP_TYPE_STRING) }, NAME_SKELETON_IMG); // --- Main component --- // @vue/component var BSkeletonImg = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SKELETON_IMG, functional: true, props: props$1R, render: function render(h, _ref) { var props = _ref.props; var aspect = props.aspect, width = props.width, height = props.height, animation = props.animation, variant = props.variant, cardImg = props.cardImg; var $img = h(BSkeleton, { props: { type: 'img', width: width, height: height, animation: animation, variant: variant }, class: _defineProperty({}, "card-img-".concat(cardImg), cardImg) }); return props.noAspect ? $img : h(BAspect, { props: { aspect: aspect } }, [$img]); } }); // Mixin to determine if an event listener has been registered var hasListenerMixin = Vue__default['default'].extend({ methods: { hasListener: function hasListener(name) { // Only includes listeners registered via `v-on:name` var $listeners = this.$listeners || {}; // Includes `v-on:name` and `this.$on('name')` registered 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; } } }); var LIGHT = 'light'; var DARK = 'dark'; // --- Props --- var props$1S = makePropsConfigurable({ variant: makeProp(PROP_TYPE_STRING) }, NAME_TR); // --- Main component --- // TODO: // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component var BTr = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TR, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide: function provide() { return { bvTableTr: this }; }, inject: { bvTableRowGroup: { default: /* istanbul ignore next */ function _default() { return {}; } } }, inheritAttrs: false, props: props$1S, computed: { // Sniffed by `<b-td>` / `<b-th>` inTbody: function inTbody() { return this.bvTableRowGroup.isTbody; }, // Sniffed by `<b-td>` / `<b-th>` inThead: function inThead() { return this.bvTableRowGroup.isThead; }, // Sniffed by `<b-td>` / `<b-th>` inTfoot: function inTfoot() { return this.bvTableRowGroup.isTfoot; }, // Sniffed by `<b-td>` / `<b-th>` isDark: function isDark() { return this.bvTableRowGroup.isDark; }, // Sniffed by `<b-td>` / `<b-th>` isStacked: function isStacked() { return this.bvTableRowGroup.isStacked; }, // Sniffed by `<b-td>` / `<b-th>` isResponsive: function isResponsive() { return this.bvTableRowGroup.isResponsive; }, // Sniffed by `<b-td>` / `<b-th>` // Sticky headers are only supported in thead isStickyHeader: function isStickyHeader() { return this.bvTableRowGroup.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 hasStickyHeader: function hasStickyHeader() { return !this.isStacked && this.bvTableRowGroup.hasStickyHeader; }, // Sniffed by `<b-td>` / `<b-th>` tableVariant: function tableVariant() { return this.bvTableRowGroup.tableVariant; }, // Sniffed by `<b-td>` / `<b-th>` headVariant: function headVariant() { return this.inThead ? this.bvTableRowGroup.headVariant : null; }, // Sniffed by `<b-td>` / `<b-th>` footVariant: function footVariant() { return this.inTfoot ? this.bvTableRowGroup.footVariant : null; }, isRowDark: function isRowDark() { return this.headVariant === LIGHT || this.footVariant === LIGHT ? /* istanbul ignore next */ false : this.headVariant === DARK || this.footVariant === DARK ? /* istanbul ignore next */ true : this.isDark; }, trClasses: function trClasses() { var variant = this.variant; return [variant ? "".concat(this.isRowDark ? 'bg' : 'table', "-").concat(variant) : null]; }, trAttrs: function trAttrs() { return _objectSpread2({ role: 'row' }, this.bvAttrs); } }, render: function render(h) { return h('tr', { class: this.trClasses, attrs: this.trAttrs, // Pass native listeners to child on: this.bvListeners }, this.normalizeSlot()); } }); var props$1T = {}; // --- Mixin --- // @vue/component var bottomRowMixin = Vue__default['default'].extend({ props: props$1T, methods: { renderBottomRow: function renderBottomRow() { var fields = this.computedFields, stacked = this.stacked, tbodyTrClass = this.tbodyTrClass, tbodyTrAttr = this.tbodyTrAttr; 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(SLOT_NAME_BOTTOM_ROW) || stacked === true || stacked === '') { return h(); } return h(BTr, { staticClass: 'b-table-bottom-row', class: [isFunction(tbodyTrClass) ? /* istanbul ignore next */ tbodyTrClass(null, 'row-bottom') : tbodyTrClass], attrs: isFunction(tbodyTrAttr) ? /* istanbul ignore next */ tbodyTrAttr(null, 'row-bottom') : tbodyTrAttr, key: 'b-bottom-row' }, this.normalizeSlot(SLOT_NAME_BOTTOM_ROW, { columns: fields.length, fields: fields })); } } }); // Parse a rowspan or colspan into a digit (or `null` if < `1` ) var parseSpan = function parseSpan(value) { value = toInteger(value, 0); return value > 0 ? value : null; }; /* istanbul ignore next */ var spanValidator = function spanValidator(value) { return isUndefinedOrNull(value) || parseSpan(value) > 0; }; // --- Props --- var props$1U = makePropsConfigurable({ colspan: makeProp(PROP_TYPE_NUMBER_STRING, null, spanValidator), rowspan: makeProp(PROP_TYPE_NUMBER_STRING, null, spanValidator), stackedHeading: makeProp(PROP_TYPE_STRING), stickyColumn: makeProp(PROP_TYPE_BOOLEAN, false), variant: makeProp(PROP_TYPE_STRING) }, NAME_TABLE_CELL); // --- Main component --- // TODO: // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component var BTd = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TABLE_CELL, // Mixin order is important! mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], inject: { bvTableTr: { default: /* istanbul ignore next */ function _default() { return {}; } } }, inheritAttrs: false, props: props$1U, computed: { // Overridden by `<b-th>` tag: function tag() { 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; }, // We only support stacked-heading in tbody in stacked mode isStackedCell: function isStackedCell() { return this.inTbody && this.isStacked; }, isResponsive: function isResponsive() { return this.bvTableTr.isResponsive; }, // 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` isStickyHeader: function isStickyHeader() { return this.bvTableTr.isStickyHeader; }, // Needed to handle header background classes, due to lack of // background color inheritance with Bootstrap v4 table CSS hasStickyHeader: function hasStickyHeader() { return this.bvTableTr.hasStickyHeader; }, // 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` isStickyColumn: function isStickyColumn() { 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() { 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); }, // We use computed props here for improved performance by caching // the results of the string interpolation cellClasses: function cellClasses() { var variant = this.variant, headVariant = this.headVariant, isStickyColumn = this.isStickyColumn; if (!variant && this.isStickyHeader && !headVariant || !variant && isStickyColumn && this.inTfoot && !this.footVariant || !variant && isStickyColumn && this.inThead && !headVariant || !variant && isStickyColumn && this.inTbody) { // Needed for sticky-header mode as Bootstrap v4 table cells do // not inherit parent's `background-color` variant = this.rowVariant || this.tableVariant || 'b-table-default'; } return [variant ? "".concat(this.isDark ? 'bg' : 'table', "-").concat(variant) : null, isStickyColumn ? 'b-table-sticky-column' : null]; }, cellAttrs: function cellAttrs() { var stackedHeading = this.stackedHeading; // 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 (isTag(this.tag, 'th')) { // th's in tbody role = 'rowheader'; scope = rowspan > 0 ? 'rowgroup' : 'row'; } return _objectSpread2(_objectSpread2({ colspan: colspan, rowspan: rowspan, role: role, scope: scope }, this.bvAttrs), {}, { // Add in the stacked cell label data-attribute if in // stacked mode (if a stacked heading label is provided) 'data-label': this.isStackedCell && !isUndefinedOrNull(stackedHeading) ? /* istanbul ignore next */ toString$1(stackedHeading) : null }); } }, render: function render(h) { var $content = [this.normalizeSlot()]; return h(this.tag, { class: this.cellClasses, attrs: this.cellAttrs, // Transfer any native listeners on: this.bvListeners }, [this.isStackedCell ? h('div', [$content]) : $content]); } }); var MODEL_PROP_NAME_BUSY = 'busy'; var MODEL_EVENT_NAME_BUSY = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_BUSY; // --- Props --- var props$1V = _defineProperty({}, MODEL_PROP_NAME_BUSY, makeProp(PROP_TYPE_BOOLEAN, false)); // --- Mixin --- // @vue/component var busyMixin = Vue__default['default'].extend({ props: props$1V, data: function data() { return { localBusy: false }; }, computed: { computedBusy: function computedBusy() { return this[MODEL_PROP_NAME_BUSY] || this.localBusy; } }, watch: { localBusy: function localBusy(newValue, oldValue) { if (newValue !== oldValue) { this.$emit(MODEL_EVENT_NAME_BUSY, newValue); } } }, methods: { // Event handler helper stopIfBusy: function stopIfBusy(event) { // If table is busy (via provider) then don't propagate if (this.computedBusy) { stopEvent(event); return true; } return false; }, // Render the busy indicator or return `null` if not busy renderBusy: function renderBusy() { var tbodyTrClass = this.tbodyTrClass, tbodyTrAttr = this.tbodyTrAttr; var h = this.$createElement; // Return a busy indicator row, or `null` if not busy if (this.computedBusy && this.hasNormalizedSlot(SLOT_NAME_TABLE_BUSY)) { return h(BTr, { staticClass: 'b-table-busy-slot', class: [isFunction(tbodyTrClass) ? /* istanbul ignore next */ tbodyTrClass(null, SLOT_NAME_TABLE_BUSY) : tbodyTrClass], attrs: isFunction(tbodyTrAttr) ? /* istanbul ignore next */ tbodyTrAttr(null, SLOT_NAME_TABLE_BUSY) : tbodyTrAttr, key: 'table-busy-slot' }, [h(BTd, { props: { colspan: this.computedFields.length || null } }, [this.normalizeSlot(SLOT_NAME_TABLE_BUSY)])]); } // We return `null` here so that we can determine if we need to // render the table items rows or not return null; } } }); var props$1W = { caption: makeProp(PROP_TYPE_STRING), captionHtml: makeProp(PROP_TYPE_STRING) // `caption-top` is part of table-render mixin (styling) // captionTop: makeProp(PROP_TYPE_BOOLEAN, false) }; // --- Mixin --- // @vue/component var captionMixin = Vue__default['default'].extend({ props: props$1W, computed: { captionId: function captionId() { return this.isStacked ? this.safeId('_caption_') : null; } }, methods: { renderCaption: function renderCaption() { var caption = this.caption, captionHtml = this.captionHtml; var h = this.$createElement; var $caption = h(); var hasCaptionSlot = this.hasNormalizedSlot(SLOT_NAME_TABLE_CAPTION); if (hasCaptionSlot || caption || captionHtml) { $caption = h('caption', { attrs: { id: this.captionId }, domProps: hasCaptionSlot ? {} : htmlOrText(captionHtml, caption), key: 'caption', ref: 'caption' }, this.normalizeSlot(SLOT_NAME_TABLE_CAPTION)); } return $caption; } } }); var props$1X = {}; // --- Mixin --- // @vue/component var colgroupMixin = Vue__default['default'].extend({ methods: { renderColgroup: function renderColgroup() { var fields = this.computedFields; var h = this.$createElement; var $colgroup = h(); if (this.hasNormalizedSlot(SLOT_NAME_TABLE_COLGROUP)) { $colgroup = h('colgroup', { key: 'colgroup' }, [this.normalizeSlot(SLOT_NAME_TABLE_COLGROUP, { columns: fields.length, fields: fields })]); } return $colgroup; } } }); var props$1Y = { emptyFilteredHtml: makeProp(PROP_TYPE_STRING), emptyFilteredText: makeProp(PROP_TYPE_STRING, 'There are no records matching your request'), emptyHtml: makeProp(PROP_TYPE_STRING), emptyText: makeProp(PROP_TYPE_STRING, 'There are no records to show'), showEmpty: makeProp(PROP_TYPE_BOOLEAN, false) }; // --- Mixin --- // @vue/component var emptyMixin = Vue__default['default'].extend({ props: props$1Y, methods: { renderEmpty: function renderEmpty() { var items = this.computedItems; var h = this.$createElement; var $empty = h(); if (this.showEmpty && (!items || items.length === 0) && !(this.computedBusy && this.hasNormalizedSlot(SLOT_NAME_TABLE_BUSY))) { var fields = this.computedFields, isFiltered = this.isFiltered, emptyText = this.emptyText, emptyHtml = this.emptyHtml, emptyFilteredText = this.emptyFilteredText, emptyFilteredHtml = this.emptyFilteredHtml, tbodyTrClass = this.tbodyTrClass, tbodyTrAttr = this.tbodyTrAttr; $empty = this.normalizeSlot(isFiltered ? SLOT_NAME_EMPTYFILTERED : SLOT_NAME_EMPTY, { emptyFilteredHtml: emptyFilteredHtml, emptyFilteredText: emptyFilteredText, emptyHtml: emptyHtml, emptyText: emptyText, fields: fields, // Not sure why this is included, as it will always be an empty array items: items }); if (!$empty) { $empty = h('div', { class: ['text-center', 'my-2'], domProps: isFiltered ? htmlOrText(emptyFilteredHtml, emptyFilteredText) : htmlOrText(emptyHtml, emptyText) }); } $empty = h(BTd, { props: { colspan: fields.length || null } }, [h('div', { attrs: { role: 'alert', 'aria-live': 'polite' } }, [$empty])]); $empty = h(BTr, { staticClass: 'b-table-empty-row', class: [isFunction(tbodyTrClass) ? /* istanbul ignore next */ tbodyTrClass(null, 'row-empty') : tbodyTrClass], attrs: isFunction(tbodyTrAttr) ? /* istanbul ignore next */ tbodyTrAttr(null, 'row-empty') : tbodyTrAttr, key: isFiltered ? 'b-empty-filtered-row' : 'b-empty-row' }, [$empty]); } return $empty; } } }); // 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' // // Strings are returned as-is // Numbers get converted to string // `null` and `undefined` values are filtered out // Dates are converted to their native string format var stringifyObjectValues = function stringifyObjectValues(value) { if (isUndefinedOrNull(value)) { return ''; } // Arrays are also object, and keys just returns the array indexes // Date objects we convert to strings if (isObject(value) && !isDate(value)) { return keys(value).sort() // Sort to prevent SSR issues on pre-rendered sorted tables .map(function (k) { return stringifyObjectValues(value[k]); }).filter(function (v) { return !!v; }) // Ignore empty strings .join(' '); } return toString$1(value); }; // Constants used by table helpers var FIELD_KEY_CELL_VARIANT = '_cellVariants'; var FIELD_KEY_ROW_VARIANT = '_rowVariant'; var FIELD_KEY_SHOW_DETAILS = '_showDetails'; // Object of item keys that should be ignored for headers and // stringification and filter events var IGNORED_FIELD_KEYS = [FIELD_KEY_CELL_VARIANT, FIELD_KEY_ROW_VARIANT, FIELD_KEY_SHOW_DETAILS].reduce(function (result, key) { return _objectSpread2(_objectSpread2({}, result), {}, _defineProperty({}, key, 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 sanitizeRow = function sanitizeRow(row, ignoreFields, includeFields) { var fieldsObj = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; // We first need to format the row based on the field configurations // This ensures that we add formatted values for keys that may not // exist in the row itself var formattedRow = keys(fieldsObj).reduce(function (result, key) { var field = fieldsObj[key]; var filterByFormatted = field.filterByFormatted; var formatter = isFunction(filterByFormatted) ? /* istanbul ignore next */ filterByFormatted : filterByFormatted ? /* istanbul ignore next */ field.formatter : null; if (isFunction(formatter)) { result[key] = formatter(row[key], key, row); } return result; }, clone(row)); // Determine the allowed keys: // - Ignore special fields that start with `_` // - Ignore fields in the `ignoreFields` array // - Include only fields in the `includeFields` array var allowedKeys = keys(formattedRow).filter(function (key) { return !IGNORED_FIELD_KEYS[key] && !(isArray(ignoreFields) && ignoreFields.length > 0 && arrayIncludes(ignoreFields, key)) && !(isArray(includeFields) && includeFields.length > 0 && !arrayIncludes(includeFields, key)); }); return pick(formattedRow, allowedKeys); }; // TODO: Add option to stringify `scopedSlot` items var stringifyRecordValues = function stringifyRecordValues(row, ignoreFields, includeFields, fieldsObj) { return isObject(row) ? stringifyObjectValues(sanitizeRow(row, ignoreFields, includeFields, fieldsObj)) : /* istanbul ignore next */ ''; }; var DEBOUNCE_DEPRECATED_MSG = 'Prop "filter-debounce" is deprecated. Use the debounce feature of "<b-form-input>" instead.'; // --- Props --- var props$1Z = { filter: makeProp([].concat(_toConsumableArray(PROP_TYPE_ARRAY_OBJECT_STRING), [PROP_TYPE_REG_EXP])), filterDebounce: makeProp(PROP_TYPE_NUMBER_STRING, 0, function (value) { return RX_DIGITS.test(String(value)); }), filterFunction: makeProp(PROP_TYPE_FUNCTION), filterIgnoredFields: makeProp(PROP_TYPE_ARRAY, []), filterIncludedFields: makeProp(PROP_TYPE_ARRAY, []) }; // --- Mixin --- // @vue/component var filteringMixin = Vue__default['default'].extend({ props: props$1Z, 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 concat(this.filterIgnoredFields || []).filter(identity); }, computedFilterIncluded: function computedFilterIncluded() { return concat(this.filterIncludedFields || []).filter(identity); }, computedFilterDebounce: function computedFilterDebounce() { var ms = toInteger(this.filterDebounce, 0); /* istanbul ignore next */ if (ms > 0) { warn(DEBOUNCE_DEPRECATED_MSG, NAME_TABLE); } return ms; }, localFiltering: function localFiltering() { return this.hasProvider ? !!this.noProviderFiltering : true; }, // For watching changes to `filteredItems` vs `localItems` filteredCheck: function filteredCheck() { var filteredItems = this.filteredItems, localItems = this.localItems, localFilter = this.localFilter; return { filteredItems: filteredItems, localItems: localItems, localFilter: localFilter }; }, // Sanitized/normalize filter-function prop localFilterFn: function localFilterFn() { // Return `null` to signal to use internal filter function var filterFunction = this.filterFunction; return hasPropFunction(filterFunction) ? filterFunction : null; }, // Returns the records in `localItems` that match the filter criteria // Returns the original `localItems` array if not sorting filteredItems: function filteredItems() { // Note the criteria is debounced and sanitized var items = this.localItems, 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(newValue) { if (!newValue && this.$_filterTimer) { this.clearFilterTimer(); 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; this.clearFilterTimer(); 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(EVENT_NAME_FILTERED, filteredItems, filteredItems.length); } this.isFiltered = isFiltered; }, isFiltered: function isFiltered(newValue, oldValue) { if (newValue === false && oldValue === true) { // We need to emit a filtered event if `isFiltered` transitions from `true` to // `false` so that users can update their pagination controls var localItems = this.localItems; this.$emit(EVENT_NAME_FILTERED, localItems, localItems.length); } } }, created: function created() { var _this2 = this; // Create private non-reactive props 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() { this.clearFilterTimer(); }, methods: { clearFilterTimer: function clearFilterTimer() { clearTimeout(this.$_filterTimer); this.$_filterTimer = null; }, 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, '\\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; } } }); 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 _makeModelMixin$i = makeModelMixin('value', { type: PROP_TYPE_ARRAY, defaultValue: [] }), modelMixin$h = _makeModelMixin$i.mixin, modelProps$h = _makeModelMixin$i.props, MODEL_PROP_NAME$h = _makeModelMixin$i.prop, MODEL_EVENT_NAME$h = _makeModelMixin$i.event; var props$1_ = sortKeys(_objectSpread2(_objectSpread2({}, modelProps$h), {}, _defineProperty({ fields: makeProp(PROP_TYPE_ARRAY, null), // Provider mixin adds in `Function` type items: makeProp(PROP_TYPE_ARRAY, []), // Primary key for record // If provided the value in each row must be unique! primaryKey: makeProp(PROP_TYPE_STRING) }, MODEL_PROP_NAME$h, makeProp(PROP_TYPE_ARRAY, [])))); // --- Mixin --- // @vue/component var itemsMixin = Vue__default['default'].extend({ mixins: [modelMixin$h], props: props$1_, data: function data() { var items = this.items; return { // Our local copy of the items // Must be an array localItems: isArray(items) ? 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 || /* istanbul ignore next */ []).slice(); }, context: function context() { // Current state of sorting, filtering and pagination props/values return { filter: this.localFilter, sortBy: this.localSortBy, sortDesc: this.localSortDesc, perPage: mathMax(toInteger(this.perPage, 0), 0), currentPage: mathMax(toInteger(this.currentPage, 0), 1), apiUrl: this.apiUrl }; } }, watch: { items: function items(newValue) { // Set `localItems`/`filteredItems` to a copy of the provided array this.localItems = isArray(newValue) ? newValue.slice() : []; }, // Watch for changes on `computedItems` and update the `v-model` computedItems: function computedItems(newValue, oldValue) { if (!looseEqual(newValue, oldValue)) { this.$emit(MODEL_EVENT_NAME$h, newValue); } }, // Watch for context changes context: function context(newValue, oldValue) { // Emit context information for external paging/filtering/sorting handling if (!looseEqual(newValue, oldValue)) { this.$emit(EVENT_NAME_CONTEXT_CHANGED, newValue); } } }, mounted: function mounted() { // Initially update the `v-model` of displayed items this.$emit(MODEL_EVENT_NAME$h, 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; } } }); var props$1$ = { currentPage: makeProp(PROP_TYPE_NUMBER_STRING, 1), perPage: makeProp(PROP_TYPE_NUMBER_STRING, 0) }; // --- Mixin --- // @vue/component var paginationMixin$1 = Vue__default['default'].extend({ props: props$1$, computed: { localPaging: function localPaging() { return this.hasProvider ? !!this.noProviderPaging : true; }, paginatedItems: function paginatedItems() { var items = this.sortedItems || this.filteredItems || this.localItems || []; var currentPage = mathMax(toInteger(this.currentPage, 1), 1); var perPage = mathMax(toInteger(this.perPage, 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 ROOT_EVENT_NAME_REFRESHED = getRootEventName(NAME_TABLE, EVENT_NAME_REFRESHED); var ROOT_ACTION_EVENT_NAME_REFRESH = getRootActionEventName(NAME_TABLE, EVENT_NAME_REFRESH); // --- Props --- var props$20 = { // Passed to the context object // Not used by `<b-table>` directly apiUrl: makeProp(PROP_TYPE_STRING), // Adds in 'Function' support items: makeProp(PROP_TYPE_ARRAY_FUNCTION, []), noProviderFiltering: makeProp(PROP_TYPE_BOOLEAN, false), noProviderPaging: makeProp(PROP_TYPE_BOOLEAN, false), noProviderSorting: makeProp(PROP_TYPE_BOOLEAN, false) }; // --- Mixin --- // @vue/component var providerMixin = Vue__default['default'].extend({ mixins: [listenOnRootMixin], props: props$20, 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(newValue) { // If a new provider has been specified, trigger an update if (this.hasProvider || isFunction(newValue)) { this.$nextTick(this._providerUpdate); } }, providerTriggerContext: function providerTriggerContext(newValue, oldValue) { // Trigger the provider to update as the relevant context values have changed. if (!looseEqual(newValue, oldValue)) { 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(ROOT_ACTION_EVENT_NAME_REFRESH, function (id) { if (id === _this.id || id === _this) { _this.refresh(); } }); }, methods: { refresh: function refresh() { var items = this.items, refresh = this.refresh; // Public Method: Force a refresh of the provider function this.$off(EVENT_NAME_REFRESHED, 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(EVENT_NAME_REFRESHED, refresh); } } else { this.clearSelected(); if (this.hasProvider) { this.$nextTick(this._providerUpdate); } else { /* istanbul ignore next */ this.localItems = isArray(items) ? items.slice() : []; } } }, // Provider related methods _providerSetLocal: function _providerSetLocal(items) { this.localItems = isArray(items) ? items.slice() : []; this.localBusy = false; this.$emit(EVENT_NAME_REFRESHED); // New root emit if (this.id) { this.emitOnRoot(ROOT_EVENT_NAME_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.", NAME_TABLE); _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, "."), NAME_TABLE); _this2.localBusy = false; _this2.$off(EVENT_NAME_REFRESHED, _this2.refresh); } }); } } }); var SELECT_MODES = ['range', 'multi', 'single']; // --- Props --- var props$21 = { // Disable use of click handlers for row selection noSelectOnClick: makeProp(PROP_TYPE_BOOLEAN, false), selectMode: makeProp(PROP_TYPE_STRING, 'multi', function (value) { return arrayIncludes(SELECT_MODES, value); }), selectable: makeProp(PROP_TYPE_BOOLEAN, false), selectedVariant: makeProp(PROP_TYPE_STRING, 'active') }; // --- Mixin --- // @vue/component var selectableMixin = Vue__default['default'].extend({ props: props$21, 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() { var selectedRows = this.selectedRows; return this.isSelectable && selectedRows && selectedRows.length > 0 && selectedRows.some(identity); }, selectableIsMultiSelect: function selectableIsMultiSelect() { return this.isSelectable && arrayIncludes(['range', 'multi'], this.selectMode); }, selectableTableClasses: function selectableTableClasses() { var _ref; var isSelectable = this.isSelectable; return _ref = { 'b-table-selectable': isSelectable }, _defineProperty(_ref, "b-table-select-".concat(this.selectMode), isSelectable), _defineProperty(_ref, 'b-table-selecting', this.selectableHasSelection), _defineProperty(_ref, 'b-table-selectable-no-click', 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(newValue, oldValue) { // Reset for selectable var equal = false; if (this.isSelectable && this.selectedRows.length > 0) { // Quick check against array length equal = isArray(newValue) && isArray(oldValue) && newValue.length === oldValue.length; for (var i = 0; equal && i < newValue.length; i++) { // Look for the first non-loosely equal row, after ignoring reserved fields equal = looseEqual(sanitizeRow(newValue[i]), sanitizeRow(oldValue[i])); } } if (!equal) { this.clearSelected(); } }, selectable: function selectable(newValue) { this.clearSelected(); this.setSelectionHandlers(newValue); }, selectMode: function selectMode() { this.clearSelected(); }, hasSelectableRowClick: function hasSelectableRowClick(newValue) { this.clearSelected(); this.setSelectionHandlers(!newValue); }, selectedRows: function selectedRows(_selectedRows, oldValue) { var _this = this; if (this.isSelectable && !looseEqual(_selectedRows, oldValue)) { 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(EVENT_NAME_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 ? createArray(length, 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); } 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](EVENT_NAME_ROW_CLICKED, this.selectionHandler); // Clear selection on filter, pagination, and sort changes this[method](EVENT_NAME_FILTERED, this.clearSelected); this[method](EVENT_NAME_CONTEXT_CHANGED, this.clearSelected); }, selectionHandler: function selectionHandler(item, index, event) { /* 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, selectedLastRow = this.selectedLastRow; 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 (selectedLastRow > -1 && event.shiftKey) { // range for (var idx = mathMin(selectedLastRow, index); idx <= mathMax(selectedLastRow, index); idx++) { selectedRows[idx] = true; } selected = true; } else { if (!(event.ctrlKey || event.metaKey)) { // Clear range selection if any selectedRows = []; selected = true; } this.selectedLastRow = selected ? index : -1; } } selectedRows[index] = selected; this.selectedRows = selectedRows; } } }); /* * 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]; }); }; var normalizeValue = function normalizeValue(value) { if (isUndefinedOrNull(value)) { return ''; } if (isNumeric(value)) { return toFloat(value, value); } return value; }; // Default sort compare routine // // 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) { var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref$sortBy = _ref.sortBy, sortBy = _ref$sortBy === void 0 ? null : _ref$sortBy, _ref$formatter = _ref.formatter, formatter = _ref$formatter === void 0 ? null : _ref$formatter, _ref$locale = _ref.locale, locale = _ref$locale === void 0 ? undefined : _ref$locale, _ref$localeOptions = _ref.localeOptions, localeOptions = _ref$localeOptions === void 0 ? {} : _ref$localeOptions, _ref$nullLast = _ref.nullLast, nullLast = _ref$nullLast === void 0 ? false : _ref$nullLast; // Get the value by `sortBy` var aa = get(a, sortBy, null); var bb = get(b, sortBy, null); // Apply user-provided formatter if (isFunction(formatter)) { aa = formatter(aa, sortBy, a); bb = formatter(bb, sortBy, b); } // Internally normalize value // `null` / `undefined` => '' // `'0'` => `0` aa = normalizeValue(aa); bb = normalizeValue(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` / '' last return 1; } else if (nullLast && aa !== '' && bb === '') { // Special case when sorting `null` / `undefined` / '' last return -1; } // Do localized string comparison return stringifyObjectValues(aa).localeCompare(stringifyObjectValues(bb), locale, localeOptions); }; var _props, _watch$h; var MODEL_PROP_NAME_SORT_BY = 'sortBy'; var MODEL_EVENT_NAME_SORT_BY = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_SORT_BY; var MODEL_PROP_NAME_SORT_DESC = 'sortDesc'; var MODEL_EVENT_NAME_SORT_DESC = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_SORT_DESC; var SORT_DIRECTION_ASC = 'asc'; var SORT_DIRECTION_DESC = 'desc'; var SORT_DIRECTION_LAST = 'last'; var SORT_DIRECTIONS = [SORT_DIRECTION_ASC, SORT_DIRECTION_DESC, SORT_DIRECTION_LAST]; // --- Props --- var props$22 = (_props = { labelSortAsc: makeProp(PROP_TYPE_STRING, 'Click to sort Ascending'), labelSortClear: makeProp(PROP_TYPE_STRING, 'Click to clear sorting'), labelSortDesc: makeProp(PROP_TYPE_STRING, 'Click to sort Descending'), noFooterSorting: makeProp(PROP_TYPE_BOOLEAN, false), noLocalSorting: makeProp(PROP_TYPE_BOOLEAN, false), // 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) noSortReset: makeProp(PROP_TYPE_BOOLEAN, false) }, _defineProperty(_props, MODEL_PROP_NAME_SORT_BY, makeProp(PROP_TYPE_STRING)), _defineProperty(_props, "sortCompare", makeProp(PROP_TYPE_FUNCTION)), _defineProperty(_props, "sortCompareLocale", makeProp(PROP_TYPE_ARRAY_STRING)), _defineProperty(_props, "sortCompareOptions", makeProp(PROP_TYPE_OBJECT, { numeric: true })), _defineProperty(_props, MODEL_PROP_NAME_SORT_DESC, makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_props, "sortDirection", makeProp(PROP_TYPE_STRING, SORT_DIRECTION_ASC, function (value) { return arrayIncludes(SORT_DIRECTIONS, value); })), _defineProperty(_props, "sortIconLeft", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_props, "sortNullLast", makeProp(PROP_TYPE_BOOLEAN, false)), _props); // --- Mixin --- // @vue/component var sortingMixin = Vue__default['default'].extend({ props: props$22, data: function data() { return { localSortBy: this[MODEL_PROP_NAME_SORT_BY] || '', localSortDesc: this[MODEL_PROP_NAME_SORT_DESC] || false }; }, computed: { localSorting: function localSorting() { return this.hasProvider ? !!this.noProviderSorting : !this.noLocalSorting; }, isSortable: function isSortable() { return this.computedFields.some(function (f) { return f.sortable; }); }, // Sorts the filtered items and returns a new array of the sorted items // When not sorted, the original items array will be returned sortedItems: function sortedItems() { var sortBy = this.localSortBy, sortDesc = this.localSortDesc, locale = this.sortCompareLocale, nullLast = this.sortNullLast, sortCompare = this.sortCompare, localSorting = this.localSorting; var items = (this.filteredItems || this.localItems || []).slice(); var localeOptions = _objectSpread2(_objectSpread2({}, this.sortCompareOptions), {}, { usage: 'sort' }); if (sortBy && localSorting) { var field = this.computedFieldsObj[sortBy] || {}; var sortByFormatted = field.sortByFormatted; var formatter = isFunction(sortByFormatted) ? /* istanbul ignore next */ 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; // Call user provided `sortCompare` routine first if (isFunction(sortCompare)) { // TODO: // Change the `sortCompare` signature to the one of `defaultSortCompare` // with the next major version bump result = sortCompare(a, b, sortBy, sortDesc, formatter, localeOptions, locale); } // Fallback to built-in `defaultSortCompare` if `sortCompare` // is not defined or returns `null`/`false` if (isUndefinedOrNull(result) || result === false) { result = defaultSortCompare(a, b, { sortBy: sortBy, formatter: formatter, locale: locale, localeOptions: localeOptions, nullLast: nullLast }); } // Negate result if sorting in descending order return (result || 0) * (sortDesc ? -1 : 1); }); } return items; } }, watch: (_watch$h = { /* istanbul ignore next: pain in the butt to test */ isSortable: function isSortable(newValue) { if (newValue) { if (this.isSortable) { this.$on(EVENT_NAME_HEAD_CLICKED, this.handleSort); } } else { this.$off(EVENT_NAME_HEAD_CLICKED, this.handleSort); } } }, _defineProperty(_watch$h, MODEL_PROP_NAME_SORT_DESC, function (newValue) { /* istanbul ignore next */ if (newValue === this.localSortDesc) { return; } this.localSortDesc = newValue || false; }), _defineProperty(_watch$h, MODEL_PROP_NAME_SORT_BY, function (newValue) { /* istanbul ignore next */ if (newValue === this.localSortBy) { return; } this.localSortBy = newValue || ''; }), _defineProperty(_watch$h, "localSortDesc", function localSortDesc(newValue, oldValue) { // Emit update to sort-desc.sync if (newValue !== oldValue) { this.$emit(MODEL_EVENT_NAME_SORT_DESC, newValue); } }), _defineProperty(_watch$h, "localSortBy", function localSortBy(newValue, oldValue) { if (newValue !== oldValue) { this.$emit(MODEL_EVENT_NAME_SORT_BY, newValue); } }), _watch$h), created: function created() { if (this.isSortable) { this.$on(EVENT_NAME_HEAD_CLICKED, this.handleSort); } }, methods: { // Handlers // Need to move from thead-mixin handleSort: function handleSort(key, field, event, 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 === SORT_DIRECTION_ASC) { _this.localSortDesc = false; } else if (sortDirection === SORT_DIRECTION_DESC) { _this.localSortDesc = true; } else ; }; if (field.sortable) { var sortKey = !this.localSorting && field.sortKey ? field.sortKey : key; if (this.localSortBy === sortKey) { // Change sorting direction on current column this.localSortDesc = !this.localSortDesc; } else { // Start sorting this column ascending this.localSortBy = sortKey; // this.localSortDesc = false toggleLocalSortDesc(); } sortChanged = true; } else if (this.localSortBy && !this.noSortReset) { this.localSortBy = ''; toggleLocalSortDesc(); sortChanged = true; } if (sortChanged) { // Sorting parameters changed this.$emit(EVENT_NAME_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 === SORT_DIRECTION_ASC) { labelSorting = this.labelSortAsc; } else if (sortDirection === SORT_DIRECTION_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 props$23 = { stacked: makeProp(PROP_TYPE_BOOLEAN_STRING, false) }; // --- Mixin --- // @vue/component var stackedMixin = Vue__default['default'].extend({ props: props$23, computed: { isStacked: function isStacked() { var stacked = this.stacked; // `true` when always stacked, or returns breakpoint specified return stacked === '' ? true : stacked; }, isStackedAlways: function isStackedAlways() { return this.isStacked === true; }, stackedTableClasses: function stackedTableClasses() { var isStackedAlways = this.isStackedAlways; return _defineProperty({ 'b-table-stacked': isStackedAlways }, "b-table-stacked-".concat(this.stacked), !isStackedAlways && this.isStacked); } } }); // Includes all main table styling options // --- Props --- var props$24 = { bordered: makeProp(PROP_TYPE_BOOLEAN, false), borderless: makeProp(PROP_TYPE_BOOLEAN, false), captionTop: makeProp(PROP_TYPE_BOOLEAN, false), dark: makeProp(PROP_TYPE_BOOLEAN, false), fixed: makeProp(PROP_TYPE_BOOLEAN, false), hover: makeProp(PROP_TYPE_BOOLEAN, false), noBorderCollapse: makeProp(PROP_TYPE_BOOLEAN, false), outlined: makeProp(PROP_TYPE_BOOLEAN, false), responsive: makeProp(PROP_TYPE_BOOLEAN_STRING, false), small: makeProp(PROP_TYPE_BOOLEAN, false), // If a string, it is assumed to be the table `max-height` value stickyHeader: makeProp(PROP_TYPE_BOOLEAN_STRING, false), striped: makeProp(PROP_TYPE_BOOLEAN, false), tableClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), tableVariant: makeProp(PROP_TYPE_STRING) }; // --- Mixin --- // @vue/component var tableRendererMixin = Vue__default['default'].extend({ mixins: [attrsMixin], provide: function provide() { return { bvTable: this }; }, // Don't place attributes on root element automatically, // as table could be wrapped in responsive `<div>` inheritAttrs: false, props: props$24, computed: { // Layout related computed props isResponsive: function isResponsive() { var responsive = this.responsive; return responsive === '' ? true : responsive; }, isStickyHeader: function isStickyHeader() { var stickyHeader = this.stickyHeader; stickyHeader = stickyHeader === '' ? true : stickyHeader; return this.isStacked ? false : stickyHeader; }, wrapperClasses: function wrapperClasses() { var isResponsive = this.isResponsive; return [this.isStickyHeader ? 'b-table-sticky-header' : '', isResponsive === true ? 'table-responsive' : isResponsive ? "table-responsive-".concat(this.responsive) : ''].filter(identity); }, wrapperStyles: function wrapperStyles() { var isStickyHeader = this.isStickyHeader; return isStickyHeader && !isBoolean(isStickyHeader) ? { maxHeight: isStickyHeader } : {}; }, tableClasses: function tableClasses() { var hover = this.hover, tableVariant = this.tableVariant; hover = this.isTableSimple ? hover : 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 }, tableVariant ? "".concat(this.dark ? 'bg' : 'table', "-").concat(tableVariant) : '', // Stacked table classes this.stackedTableClasses, // Selectable classes this.selectableTableClasses]; }, tableAttrs: function tableAttrs() { var items = this.computedItems, filteredItems = this.filteredItems, fields = this.computedFields, selectableTableAttrs = this.selectableTableAttrs; var ariaAttrs = this.isTableSimple ? {} : { 'aria-busy': this.computedBusy ? 'true' : 'false', 'aria-colcount': toString$1(fields.length), // Preserve user supplied `aria-describedby`, if provided 'aria-describedby': this.bvAttrs['aria-describedby'] || this.$refs.caption ? this.captionId : null }; var rowCount = items && filteredItems && filteredItems.length > items.length ? toString$1(filteredItems.length) : null; return _objectSpread2(_objectSpread2(_objectSpread2({ // We set `aria-rowcount` before merging in `$attrs`, // in case user has supplied their own 'aria-rowcount': rowCount }, this.bvAttrs), {}, { // Now we can override any `$attrs` here id: this.safeId(), role: 'table' }, ariaAttrs), selectableTableAttrs); } }, render: function render(h) { var wrapperClasses = this.wrapperClasses, renderCaption = this.renderCaption, renderColgroup = this.renderColgroup, renderThead = this.renderThead, renderTbody = this.renderTbody, renderTfoot = this.renderTfoot; var $content = []; if (this.isTableSimple) { $content.push(this.normalizeSlot()); } else { // Build the `<caption>` (from caption mixin) $content.push(renderCaption ? renderCaption() : null); // Build the `<colgroup>` $content.push(renderColgroup ? renderColgroup() : null); // Build the `<thead>` $content.push(renderThead ? renderThead() : null); // Build the `<tbody>` $content.push(renderTbody ? renderTbody() : null); // Build the `<tfoot>` $content.push(renderTfoot ? renderTfoot() : null); } // Assemble `<table>` var $table = h('table', { staticClass: 'table b-table', class: this.tableClasses, attrs: this.tableAttrs, key: 'b-table' }, $content.filter(identity)); // Add responsive/sticky wrapper if needed and return table return wrapperClasses.length > 0 ? h('div', { class: wrapperClasses, style: this.wrapperStyles, key: 'wrap' }, [$table]) : $table; } }); var props$25 = makePropsConfigurable({ tbodyTransitionHandlers: makeProp(PROP_TYPE_OBJECT), tbodyTransitionProps: makeProp(PROP_TYPE_OBJECT) }, NAME_TBODY); // --- Main component --- // TODO: // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component var BTbody = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TBODY, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide: function provide() { return { bvTableRowGroup: this }; }, inject: { // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` bvTable: { default: /* istanbul ignore next */ function _default() { return {}; } } }, inheritAttrs: false, props: props$25, computed: { // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isTbody: function isTbody() { return true; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isDark: function isDark() { return this.bvTable.dark; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isStacked: function isStacked() { return this.bvTable.isStacked; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isResponsive: function isResponsive() { return this.bvTable.isResponsive; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` // Sticky headers are only supported in thead isStickyHeader: function isStickyHeader() { return false; }, // 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 hasStickyHeader: function hasStickyHeader() { return !this.isStacked && this.bvTable.stickyHeader; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` tableVariant: function tableVariant() { return this.bvTable.tableVariant; }, isTransitionGroup: function isTransitionGroup() { return this.tbodyTransitionProps || this.tbodyTransitionHandlers; }, tbodyAttrs: function tbodyAttrs() { return _objectSpread2({ role: 'rowgroup' }, this.bvAttrs); }, tbodyProps: function tbodyProps() { var tbodyTransitionProps = this.tbodyTransitionProps; return tbodyTransitionProps ? _objectSpread2(_objectSpread2({}, 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.bvListeners; } else { // Otherwise we place any listeners on the tbody element data.on = this.bvListeners; } return h(this.isTransitionGroup ? 'transition-group' : 'tbody', data, this.normalizeSlot()); } }); 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(event) { // Exit early when we don't have a target element if (!event || !event.target) { /* istanbul ignore next */ return false; } var el = event.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) ? /* istanbul ignore next */ sel.containsNode(el, true) : false; }; var props$26 = makePropsConfigurable(props$1U, NAME_TH); // --- Main component --- // TODO: // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component var BTh = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TH, extends: BTd, props: props$26, computed: { tag: function tag() { return 'th'; } } }); var props$27 = { detailsTdClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), tbodyTrAttr: makeProp(PROP_TYPE_OBJECT_FUNCTION), tbodyTrClass: makeProp([].concat(_toConsumableArray(PROP_TYPE_ARRAY_OBJECT_STRING), [PROP_TYPE_FUNCTION])) }; // --- Mixin --- // @vue/component var tbodyRowMixin = Vue__default['default'].extend({ props: props$27, methods: { // Methods for computing classes, attributes and styles for table cells getTdValues: function getTdValues(item, key, tdValue, defaultValue) { 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 defaultValue; }, getThValues: function getThValues(item, key, thValue, type, defaultValue) { 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 defaultValue; }, // 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, FIELD_KEY_SHOW_DETAILS, !item[FIELD_KEY_SHOW_DETAILS]); } }; }, // Row event handlers rowHovered: function rowHovered(event) { // `mouseenter` handler (non-bubbling) // `this.tbodyRowEvtStopped` from tbody mixin if (!this.tbodyRowEvtStopped(event)) { // `this.emitTbodyRowEvent` from tbody mixin this.emitTbodyRowEvent(EVENT_NAME_ROW_HOVERED, event); } }, rowUnhovered: function rowUnhovered(event) { // `mouseleave` handler (non-bubbling) // `this.tbodyRowEvtStopped` from tbody mixin if (!this.tbodyRowEvtStopped(event)) { // `this.emitTbodyRowEvent` from tbody mixin this.emitTbodyRowEvent(EVENT_NAME_ROW_UNHOVERED, event); } }, // Renders a TD or TH for a row's field renderTbodyRowCell: function renderTbodyRowCell(field, colIndex, item, rowIndex) { var _this2 = this; var isStacked = this.isStacked; var key = field.key, label = field.label, isRowHeader = field.isRowHeader; var h = this.$createElement; var hasDetailsSlot = this.hasNormalizedSlot(SLOT_NAME_ROW_DETAILS); var formatted = this.getFormattedValue(item, field); var stickyColumn = !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 ? isRowHeader ? BTh : BTd : isRowHeader ? 'th' : 'td'; var cellVariant = item[FIELD_KEY_CELL_VARIANT] && item[FIELD_KEY_CELL_VARIANT][key] ? item[FIELD_KEY_CELL_VARIANT][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}` class: [field.class ? field.class : '', this.getTdValues(item, key, field.tdClass, '')], props: {}, attrs: _objectSpread2({ 'aria-colindex': String(colIndex + 1) }, isRowHeader ? this.getThValues(item, key, field.thAttr, 'row', {}) : this.getTdValues(item, key, field.tdAttr, {})), key: "row-".concat(rowIndex, "-cell-").concat(colIndex, "-").concat(key) }; if (stickyColumn) { // We are using the helper BTd or BTh data.props = { stackedHeading: isStacked ? 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'] = isStacked && !isUndefinedOrNull(label) ? toString$1(label) : null; data.attrs.role = isRowHeader ? 'rowheader' : 'cell'; data.attrs.scope = 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[FIELD_KEY_SHOW_DETAILS]) }; // 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]); }, // Renders an item's row (or rows if details supported) renderTbodyRow: function renderTbodyRow(item, rowIndex) { var _this3 = this; var fields = this.computedFields, striped = this.striped, primaryKey = this.primaryKey, currentPage = this.currentPage, perPage = this.perPage, tbodyTrClass = this.tbodyTrClass, tbodyTrAttr = this.tbodyTrAttr; var h = this.$createElement; var hasDetailsSlot = this.hasNormalizedSlot(SLOT_NAME_ROW_DETAILS); var rowShowDetails = item[FIELD_KEY_SHOW_DETAILS] && hasDetailsSlot; var hasRowClickHandler = this.$listeners[EVENT_NAME_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 (currentPage && perPage && perPage > 0) { ariaRowIndex = String((currentPage - 1) * 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 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(tbodyTrClass) ? tbodyTrClass(item, 'row') : tbodyTrClass; var userTrAttrs = isFunction(tbodyTrAttr) ? /* istanbul ignore next */ tbodyTrAttr(item, 'row') : tbodyTrAttr; // Add the item row $rows.push(h(BTr, { class: [userTrClasses, selectableClasses, rowShowDetails ? 'b-table-has-details' : ''], props: { variant: item[FIELD_KEY_ROW_VARIANT] || null }, attrs: _objectSpread2(_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 }, key: "__b-table-row-".concat(rowKey, "__"), ref: 'item-rows', refInFor: true }, $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(SLOT_NAME_ROW_DETAILS, detailsScope)]); // Add a hidden row to keep table row striping consistent when details showing // Only added if the table is striped if (striped) { $rows.push( // We don't use `BTr` here as we don't need the extra functionality h('tr', { staticClass: 'd-none', attrs: { 'aria-hidden': 'true', role: 'presentation' }, key: "__b-table-details-stripe__".concat(rowKey) })); } // Add the actual details row var userDetailsTrClasses = isFunction(this.tbodyTrClass) ? /* istanbul ignore next */ this.tbodyTrClass(item, SLOT_NAME_ROW_DETAILS) : this.tbodyTrClass; var userDetailsTrAttrs = isFunction(this.tbodyTrAttr) ? /* istanbul ignore next */ this.tbodyTrAttr(item, SLOT_NAME_ROW_DETAILS) : this.tbodyTrAttr; $rows.push(h(BTr, { staticClass: 'b-table-details', class: [userDetailsTrClasses], props: { variant: item[FIELD_KEY_ROW_VARIANT] || null }, attrs: _objectSpread2(_objectSpread2({}, userDetailsTrAttrs), {}, { // Users cannot override the following attributes id: detailsId, tabindex: '-1' }), key: "__b-table-details__".concat(rowKey) }, [$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 (striped) { // Add extra placeholder if table is striped $rows.push(h()); } } // Return the row(s) return $rows; } } }); var getCellSlotName = function getCellSlotName(value) { return "cell(".concat(value || '', ")"); }; // --- Props --- var props$28 = sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$25), props$27), {}, { tbodyClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING) })); // --- Mixin --- // @vue/component var tbodyMixin = Vue__default['default'].extend({ mixins: [tbodyRowMixin], props: props$28, beforeDestroy: function beforeDestroy() { this.$_bodyFieldSlotNameCache = null; }, methods: { // Returns all the item TR elements (excludes detail and spacer rows) // `this.$refs['item-rows']` 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['item-rows']` may not always be in document order getTbodyTrs: function getTbodyTrs() { var $refs = this.$refs; var tbody = $refs.tbody ? $refs.tbody.$el || $refs.tbody : null; var trs = ($refs['item-rows'] || []).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); }) : /* istanbul ignore next */ []; }, // Returns index of a particular TBODY item TR // We set `true` on closest to include self in result getTbodyTrIndex: function getTbodyTrIndex(el) { /* 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; }, // Emits a row event, with the item object, row index and original event emitTbodyRowEvent: function emitTbodyRowEvent(type, event) { if (type && this.hasListener(type) && event && event.target) { var rowIndex = this.getTbodyTrIndex(event.target); if (rowIndex > -1) { // The array of TRs correlate to the `computedItems` array var item = this.computedItems[rowIndex]; this.$emit(type, item, rowIndex, event); } } }, tbodyRowEvtStopped: function tbodyRowEvtStopped(event) { return this.stopIfBusy && this.stopIfBusy(event); }, // Delegated row event handlers onTbodyRowKeydown: function onTbodyRowKeydown(event) { // Keyboard navigation and row click emulation var target = event.target, keyCode = event.keyCode; if (this.tbodyRowEvtStopped(event) || target.tagName !== 'TR' || !isActiveElement(target) || target.tabIndex !== 0) { // Early exit if not an item row TR return; } if (arrayIncludes([CODE_ENTER, CODE_SPACE], keyCode)) { // Emulated click for keyboard users, transfer to click handler stopEvent(event); this.onTBodyRowClicked(event); } else if (arrayIncludes([CODE_UP, CODE_DOWN, CODE_HOME, CODE_END], keyCode)) { // Keyboard navigation var rowIndex = this.getTbodyTrIndex(target); if (rowIndex > -1) { stopEvent(event); var trs = this.getTbodyTrs(); var shift = event.shiftKey; if (keyCode === CODE_HOME || shift && keyCode === CODE_UP) { // Focus first row attemptFocus(trs[0]); } else if (keyCode === CODE_END || shift && keyCode === CODE_DOWN) { // Focus last row attemptFocus(trs[trs.length - 1]); } else if (keyCode === CODE_UP && rowIndex > 0) { // Focus previous row attemptFocus(trs[rowIndex - 1]); } else if (keyCode === CODE_DOWN && rowIndex < trs.length - 1) { // Focus next row attemptFocus(trs[rowIndex + 1]); } } } }, onTBodyRowClicked: function onTBodyRowClicked(event) { // Don't emit event when the table is busy, the user clicked // on a non-disabled control or is selecting text if (this.tbodyRowEvtStopped(event) || filterEvent(event) || textSelectionActive(this.$el)) { return; } this.emitTbodyRowEvent(EVENT_NAME_ROW_CLICKED, event); }, onTbodyRowMiddleMouseRowClicked: function onTbodyRowMiddleMouseRowClicked(event) { if (!this.tbodyRowEvtStopped(event) && event.which === 2) { this.emitTbodyRowEvent(EVENT_NAME_ROW_MIDDLE_CLICKED, event); } }, onTbodyRowContextmenu: function onTbodyRowContextmenu(event) { if (!this.tbodyRowEvtStopped(event)) { this.emitTbodyRowEvent(EVENT_NAME_ROW_CONTEXTMENU, event); } }, onTbodyRowDblClicked: function onTbodyRowDblClicked(event) { if (!this.tbodyRowEvtStopped(event) && !filterEvent(event)) { this.emitTbodyRowEvent(EVENT_NAME_ROW_DBLCLICKED, event); } }, // Render the tbody element and children // Note: // Row hover handlers are handled by the tbody-row mixin // As mouseenter/mouseleave events do not bubble renderTbody: function renderTbody() { var _this = this; var items = this.computedItems, renderBusy = this.renderBusy, renderTopRow = this.renderTopRow, renderEmpty = this.renderEmpty, renderBottomRow = this.renderBottomRow; var h = this.$createElement; var hasRowClickHandler = this.hasListener(EVENT_NAME_ROW_CLICKED) || this.hasSelectableRowClick; // Prepare the tbody rows var $rows = []; // Add the item data rows or the busy slot var $busy = renderBusy ? 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 = getCellSlotName(); defaultSlotName = this.hasNormalizedSlot(defaultSlotName) ? defaultSlotName : null; this.computedFields.forEach(function (field) { var key = field.key; var slotName = getCellSlotName(key); var lowercaseSlotName = getCellSlotName(key.toLowerCase()); cache[key] = _this.hasNormalizedSlot(slotName) ? slotName : _this.hasNormalizedSlot(lowercaseSlotName) ? /* istanbul ignore next */ lowercaseSlotName : 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(renderTopRow ? 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(renderEmpty ? renderEmpty() : h()); // Static bottom row slot (hidden in visibly stacked mode // as we can't control `data-label` attr) $rows.push(renderBottomRow ? 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, { class: this.tbodyClass || null, props: pluckProps(props$25, this.$props), // BTbody transfers all native event listeners to the root element // TODO: Only set the handlers if the table is not busy on: handlers, ref: 'tbody' }, $rows); // Return the assembled tbody return $tbody; } } }); var props$29 = makePropsConfigurable({ // Supported values: 'lite', 'dark', or null footVariant: makeProp(PROP_TYPE_STRING) }, NAME_TFOOT); // --- Main component --- // TODO: // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component var BTfoot = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TFOOT, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide: function provide() { return { bvTableRowGroup: this }; }, inject: { // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` bvTable: { default: /* istanbul ignore next */ function _default() { return {}; } } }, inheritAttrs: false, props: props$29, computed: { // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isTfoot: function isTfoot() { return true; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isDark: function isDark() { return this.bvTable.dark; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isStacked: function isStacked() { return this.bvTable.isStacked; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isResponsive: function isResponsive() { return this.bvTable.isResponsive; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` // Sticky headers are only supported in thead isStickyHeader: function isStickyHeader() { return false; }, // 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 hasStickyHeader: function hasStickyHeader() { return !this.isStacked && this.bvTable.stickyHeader; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` tableVariant: function tableVariant() { return this.bvTable.tableVariant; }, tfootClasses: function tfootClasses() { return [this.footVariant ? "thead-".concat(this.footVariant) : null]; }, tfootAttrs: function tfootAttrs() { return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { role: 'rowgroup' }); } }, render: function render(h) { return h('tfoot', { class: this.tfootClasses, attrs: this.tfootAttrs, // Pass down any native listeners on: this.bvListeners }, this.normalizeSlot()); } }); var props$2a = { footClone: makeProp(PROP_TYPE_BOOLEAN, false), // Any Bootstrap theme variant (or custom) // Falls back to `headRowVariant` footRowVariant: makeProp(PROP_TYPE_STRING), // 'dark', 'light', or `null` (or custom) footVariant: makeProp(PROP_TYPE_STRING), tfootClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), tfootTrClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING) }; // --- Mixin --- // @vue/component var tfootMixin = Vue__default['default'].extend({ props: props$2a, methods: { renderTFootCustom: function renderTFootCustom() { var h = this.$createElement; if (this.hasNormalizedSlot(SLOT_NAME_CUSTOM_FOOT)) { return h(BTfoot, { class: this.tfootClass || null, props: { footVariant: this.footVariant || this.headVariant || null }, key: 'bv-tfoot-custom' }, this.normalizeSlot(SLOT_NAME_CUSTOM_FOOT, { items: this.computedItems.slice(), fields: this.computedFields.slice(), columns: this.computedFields.length })); } 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$2b = makePropsConfigurable({ // Also sniffed by `<b-tr>` / `<b-td>` / `<b-th>` // Supported values: 'lite', 'dark', or `null` headVariant: makeProp(PROP_TYPE_STRING) }, NAME_THEAD); // --- Main component --- // TODO: // In Bootstrap v5, we won't need "sniffing" as table element variants properly inherit // to the child elements, so this can be converted to a functional component // @vue/component var BThead = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_THEAD, mixins: [attrsMixin, listenersMixin, normalizeSlotMixin], provide: function provide() { return { bvTableRowGroup: this }; }, inject: { // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` bvTable: { default: /* istanbul ignore next */ function _default() { return {}; } } }, inheritAttrs: false, props: props$2b, computed: { // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isThead: function isThead() { return true; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isDark: function isDark() { return this.bvTable.dark; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isStacked: function isStacked() { return this.bvTable.isStacked; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` isResponsive: function isResponsive() { return this.bvTable.isResponsive; }, // 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` isStickyHeader: function isStickyHeader() { return !this.isStacked && this.bvTable.stickyHeader; }, // 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 hasStickyHeader: function hasStickyHeader() { return !this.isStacked && this.bvTable.stickyHeader; }, // Sniffed by `<b-tr>` / `<b-td>` / `<b-th>` tableVariant: function tableVariant() { return this.bvTable.tableVariant; }, theadClasses: function theadClasses() { return [this.headVariant ? "thead-".concat(this.headVariant) : null]; }, theadAttrs: function theadAttrs() { return _objectSpread2({ role: 'rowgroup' }, this.bvAttrs); } }, render: function render(h) { return h('thead', { class: this.theadClasses, attrs: this.theadAttrs, // Pass down any native listeners on: this.bvListeners }, this.normalizeSlot()); } }); var getHeadSlotName = function getHeadSlotName(value) { return "head(".concat(value || '', ")"); }; var getFootSlotName = function getFootSlotName(value) { return "foot(".concat(value || '', ")"); }; // --- Props --- var props$2c = { // Any Bootstrap theme variant (or custom) headRowVariant: makeProp(PROP_TYPE_STRING), // 'light', 'dark' or `null` (or custom) headVariant: makeProp(PROP_TYPE_STRING), theadClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), theadTrClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING) }; // --- Mixin --- // @vue/component var theadMixin = Vue__default['default'].extend({ props: props$2c, methods: { fieldClasses: function fieldClasses(field) { // Header field (<th>) classes return [field.class ? field.class : '', field.thClass ? field.thClass : '']; }, headClicked: function headClicked(event, field, isFoot) { if (this.stopIfBusy && this.stopIfBusy(event)) { // If table is busy (via provider) then don't propagate return; } else if (filterEvent(event)) { // 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; } stopEvent(event); this.$emit(EVENT_NAME_HEAD_CLICKED, field.key, field, event, isFoot); }, renderThead: function renderThead() { var _this = this; var isFoot = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var fields = this.computedFields, isSortable = this.isSortable, isSelectable = this.isSelectable, headVariant = this.headVariant, footVariant = this.footVariant, headRowVariant = this.headRowVariant, footRowVariant = this.footRowVariant; var h = this.$createElement; // In always stacked mode, we don't bother rendering the head/foot // Or if no field headings (empty table) if (this.isStackedAlways || fields.length === 0) { return h(); } var hasHeadClickListener = isSortable || this.hasListener(EVENT_NAME_HEAD_CLICKED); // Reference to `selectAllRows` and `clearSelected()`, if table is selectable var selectAllRows = isSelectable ? this.selectAllRows : noop; var clearSelected = isSelectable ? this.clearSelected : noop; // Helper function to generate a field <th> cell var makeCell = function makeCell(field, colIndex) { var label = field.label, labelHtml = field.labelHtml, variant = field.variant, stickyColumn = field.stickyColumn, key = field.key; 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 on = {}; if (hasHeadClickListener) { on.click = function (event) { _this.headClicked(event, field, isFoot); }; on.keydown = function (event) { var keyCode = event.keyCode; if (keyCode === CODE_ENTER || keyCode === CODE_SPACE) { _this.headClicked(event, field, isFoot); } }; } var sortAttrs = isSortable ? _this.sortTheadThAttrs(key, field, isFoot) : {}; var sortClass = isSortable ? _this.sortTheadThClasses(key, field, isFoot) : null; var sortLabel = isSortable ? _this.sortTheadThLabel(key, field, isFoot) : null; var data = { class: [_this.fieldClasses(field), sortClass], props: { variant: variant, stickyColumn: stickyColumn }, style: field.thStyle || {}, attrs: _objectSpread2(_objectSpread2({ // We only add a `tabindex` of `0` if there is a head-clicked listener // and the current field is sortable tabindex: hasHeadClickListener && field.sortable ? '0' : null, abbr: field.headerAbbr || null, title: field.headerTitle || null, 'aria-colindex': colIndex + 1, 'aria-label': ariaLabel }, _this.getThValues(null, key, field.thAttr, isFoot ? 'foot' : 'head', {})), sortAttrs), on: on, key: key }; // 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 = [getHeadSlotName(key), getHeadSlotName(key.toLowerCase()), getHeadSlotName()]; // Footer will fallback to header slot names if (isFoot) { slotNames = [getFootSlotName(key), getFootSlotName(key.toLowerCase()), getFootSlotName()].concat(_toConsumableArray(slotNames)); } var scope = { label: label, column: key, field: field, isFoot: isFoot, // Add in row select methods selectAllRows: selectAllRows, clearSelected: clearSelected }; var $content = _this.normalizeSlot(slotNames, scope) || h('div', { domProps: htmlOrText(labelHtml, 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); // Generate the row(s) var $trs = []; if (isFoot) { $trs.push(h(BTr, { class: this.tfootTrClass, props: { variant: isUndefinedOrNull(footRowVariant) ? headRowVariant : /* istanbul ignore next */ footRowVariant } }, $cells)); } else { var scope = { columns: fields.length, fields: fields, // Add in row select methods selectAllRows: selectAllRows, clearSelected: clearSelected }; $trs.push(this.normalizeSlot(SLOT_NAME_THEAD_TOP, scope) || h()); $trs.push(h(BTr, { class: this.theadTrClass, props: { variant: headRowVariant } }, $cells)); } return h(isFoot ? BTfoot : BThead, { class: (isFoot ? this.tfootClass : this.theadClass) || null, props: isFoot ? { footVariant: footVariant || headVariant || null } : { headVariant: headVariant || null }, key: isFoot ? 'bv-tfoot' : 'bv-thead' }, $trs); } } }); var props$2d = {}; // --- Mixin --- // @vue/component var topRowMixin = Vue__default['default'].extend({ methods: { renderTopRow: function renderTopRow() { var fields = this.computedFields, stacked = this.stacked, tbodyTrClass = this.tbodyTrClass, tbodyTrAttr = this.tbodyTrAttr; 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(SLOT_NAME_TOP_ROW) || stacked === true || stacked === '') { return h(); } return h(BTr, { staticClass: 'b-table-top-row', class: [isFunction(tbodyTrClass) ? tbodyTrClass(null, 'row-top') : tbodyTrClass], attrs: isFunction(tbodyTrAttr) ? tbodyTrAttr(null, 'row-top') : tbodyTrAttr, key: 'b-top-row' }, [this.normalizeSlot(SLOT_NAME_TOP_ROW, { columns: fields.length, fields: fields })]); } } }); var props$2e = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$1T), props$1V), props$1W), props$1X), props$1Y), props$1Z), props$1_), props$1$), props$20), props$21), props$22), props$23), props$24), props$28), props$2a), props$2c), props$2d)), NAME_TABLE); // --- Main component --- // @vue/component var BTable = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TABLE, // Order of mixins is important! // They are merged from first to last, followed by this component mixins: [// General mixins attrsMixin, hasListenerMixin, idMixin, normalizeSlotMixin, // Required table mixins itemsMixin, tableRendererMixin, stackedMixin, theadMixin, tfootMixin, tbodyMixin, // Table features mixins stackedMixin, filteringMixin, sortingMixin, paginationMixin$1, captionMixin, colgroupMixin, selectableMixin, emptyMixin, topRowMixin, bottomRowMixin, busyMixin, providerMixin], props: props$2e // Render function is provided by `tableRendererMixin` }); var props$2f = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$1W), props$1X), props$1_), props$23), props$24), props$28), props$2a), props$2c)), NAME_TABLE_LITE); // --- Main component --- // @vue/component var BTableLite = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TABLE_LITE, // Order of mixins is important! // They are merged from first to last, followed by this component mixins: [// General mixins attrsMixin, hasListenerMixin, idMixin, normalizeSlotMixin, // Required table mixins itemsMixin, tableRendererMixin, stackedMixin, theadMixin, tfootMixin, tbodyMixin, // Table features mixins // These are pretty lightweight, and are useful for lightweight tables captionMixin, colgroupMixin], props: props$2f // Render function is provided by `tableRendererMixin` }); var props$2g = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), props$23), props$24)), NAME_TABLE_SIMPLE); // --- Main component --- // @vue/component var BTableSimple = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TABLE_SIMPLE, // Order of mixins is important! // They are merged from first to last, followed by this component mixins: [// General mixins attrsMixin, hasListenerMixin, idMixin, normalizeSlotMixin, // Required table mixins tableRendererMixin, // Table features mixins // Stacked requires extra handling by users via // the table cell `stacked-heading` prop stackedMixin], props: props$2g, computed: { isTableSimple: function isTableSimple() { return true; } } // Render function is provided by `tableRendererMixin` }); 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 isPositiveNumber = function isPositiveNumber(value) { return value > 0; }; // --- Props --- var props$2h = makePropsConfigurable({ animation: makeProp(PROP_TYPE_STRING), columns: makeProp(PROP_TYPE_NUMBER, 5, isPositiveNumber), hideHeader: makeProp(PROP_TYPE_BOOLEAN, false), rows: makeProp(PROP_TYPE_NUMBER, 3, isPositiveNumber), showFooter: makeProp(PROP_TYPE_BOOLEAN, false), tableProps: makeProp(PROP_TYPE_OBJECT, {}) }, NAME_SKELETON_TABLE); // --- Main component --- // @vue/component var BSkeletonTable = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SKELETON_TABLE, functional: true, props: props$2h, render: function render(h, _ref) { var props = _ref.props; var animation = props.animation, columns = props.columns; var $th = h('th', [h(BSkeleton, { props: { animation: animation } })]); var $thTr = h('tr', createArray(columns, $th)); var $td = h('td', [h(BSkeleton, { props: { width: '75%', animation: animation } })]); var $tdTr = h('tr', createArray(columns, $td)); var $tbody = h('tbody', createArray(props.rows, $tdTr)); var $thead = !props.hideHeader ? h('thead', [$thTr]) : h(); var $tfoot = props.showFooter ? h('tfoot', [$thTr]) : h(); return h(BTableSimple, { props: _objectSpread2({}, props.tableProps) }, [$thead, $tbody, $tfoot]); } }); var props$2i = makePropsConfigurable({ loading: makeProp(PROP_TYPE_BOOLEAN, false) }, NAME_SKELETON_WRAPPER); // --- Main component --- // @vue/component var BSkeletonWrapper = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_SKELETON_WRAPPER, functional: true, props: props$2i, render: function render(h, _ref) { var data = _ref.data, props = _ref.props, slots = _ref.slots, scopedSlots = _ref.scopedSlots; var $slots = slots(); var $scopedSlots = scopedSlots || {}; var slotScope = {}; if (props.loading) { return h('div', a(data, { attrs: { role: 'alert', 'aria-live': 'polite', 'aria-busy': true }, staticClass: 'b-skeleton-wrapper', key: 'loading' }), normalizeSlot(SLOT_NAME_LOADING, slotScope, $scopedSlots, $slots)); } return normalizeSlot(SLOT_NAME_DEFAULT, slotScope, $scopedSlots, $slots); } }); var SkeletonPlugin = /*#__PURE__*/pluginFactory({ components: { BSkeleton: BSkeleton, BSkeletonIcon: BSkeletonIcon, BSkeletonImg: BSkeletonImg, BSkeletonTable: BSkeletonTable, BSkeletonWrapper: BSkeletonWrapper } }); var SpinnerPlugin = /*#__PURE__*/pluginFactory({ components: { BSpinner: BSpinner } }); var _watch$i; var _makeModelMixin$j = makeModelMixin('value', { type: PROP_TYPE_NUMBER }), modelMixin$i = _makeModelMixin$j.mixin, modelProps$i = _makeModelMixin$j.props, MODEL_PROP_NAME$i = _makeModelMixin$j.prop, MODEL_EVENT_NAME$i = _makeModelMixin$j.event; // --- Helper methods --- // Filter function to filter out disabled tabs var notDisabled = function notDisabled(tab) { return !tab.disabled; }; // --- Helper components --- // @vue/component var BVTabButton = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TAB_BUTTON_HELPER, inject: { bvTabs: { default: /* istanbul ignore next */ function _default() { return {}; } } }, props: { controls: makeProp(PROP_TYPE_STRING), id: makeProp(PROP_TYPE_STRING), noKeyNav: makeProp(PROP_TYPE_BOOLEAN, false), posInSet: makeProp(PROP_TYPE_NUMBER), setSize: makeProp(PROP_TYPE_NUMBER), // Reference to the child <b-tab> instance tab: makeProp(), tabIndex: makeProp(PROP_TYPE_NUMBER) }, methods: { focus: function focus() { attemptFocus(this.$refs.link); }, handleEvt: function handleEvt(event) { /* istanbul ignore next */ if (this.tab.disabled) { return; } var type = event.type, keyCode = event.keyCode, shiftKey = event.shiftKey; if (type === 'click') { stopEvent(event); this.$emit(EVENT_NAME_CLICK, event); } else if (type === 'keydown' && keyCode === CODE_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 stopEvent(event); this.$emit(EVENT_NAME_CLICK, event); } else if (type === 'keydown' && !this.noKeyNav) { // For keyboard navigation if ([CODE_UP, CODE_LEFT, CODE_HOME].indexOf(keyCode) !== -1) { stopEvent(event); if (shiftKey || keyCode === CODE_HOME) { this.$emit(EVENT_NAME_FIRST, event); } else { this.$emit(EVENT_NAME_PREV, event); } } else if ([CODE_DOWN, CODE_RIGHT, CODE_END].indexOf(keyCode) !== -1) { stopEvent(event); if (shiftKey || keyCode === CODE_END) { this.$emit(EVENT_NAME_LAST, event); } else { this.$emit(EVENT_NAME_NEXT, event); } } } } }, render: function render(h) { var id = this.id, tabIndex = this.tabIndex, setSize = this.setSize, posInSet = this.posInSet, controls = this.controls, handleEvt = this.handleEvt; var _this$tab = this.tab, title = _this$tab.title, localActive = _this$tab.localActive, disabled = _this$tab.disabled, titleItemClass = _this$tab.titleItemClass, titleLinkClass = _this$tab.titleLinkClass, titleLinkAttributes = _this$tab.titleLinkAttributes; var $link = h(BLink, { staticClass: 'nav-link', class: [{ active: localActive && !disabled, disabled: disabled }, titleLinkClass, // Apply <b-tabs> `activeNavItemClass` styles when the tab is active localActive ? this.bvTabs.activeNavItemClass : null], props: { disabled: disabled }, attrs: _objectSpread2(_objectSpread2({}, titleLinkAttributes), {}, { id: id, role: 'tab', // Roving tab index when keynav enabled tabindex: tabIndex, 'aria-selected': localActive && !disabled ? 'true' : 'false', 'aria-setsize': setSize, 'aria-posinset': posInSet, 'aria-controls': controls }), on: { click: handleEvt, keydown: handleEvt }, ref: 'link' }, [this.tab.normalizeSlot(SLOT_NAME_TITLE) || title]); return h('li', { staticClass: 'nav-item', class: [titleItemClass], attrs: { role: 'presentation' } }, [$link]); } }); // --- Props --- var navProps = omit(props$1t, ['tabs', 'isNavBar', 'cardHeader']); var props$2j = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$i), navProps), {}, { // Only applied to the currently active `<b-nav-item>` activeNavItemClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), // Only applied to the currently active `<b-tab>` // This prop is sniffed by the `<b-tab>` child activeTabClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), card: makeProp(PROP_TYPE_BOOLEAN, false), contentClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), // Synonym for 'bottom' end: makeProp(PROP_TYPE_BOOLEAN, false), // This prop is sniffed by the `<b-tab>` child lazy: makeProp(PROP_TYPE_BOOLEAN, false), navClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), navWrapperClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), noFade: makeProp(PROP_TYPE_BOOLEAN, false), noKeyNav: makeProp(PROP_TYPE_BOOLEAN, false), noNavStyle: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'div') })), NAME_TABS); // --- Main component --- // @vue/component var BTabs = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TABS, mixins: [idMixin, modelMixin$i, normalizeSlotMixin], provide: function provide() { return { bvTabs: this }; }, props: props$2j, data: function data() { return { // Index of current tab currentTab: toInteger(this[MODEL_PROP_NAME$i], -1), // Array of direct child `<b-tab>` instances, in DOM order tabs: [], // Array of child instances registered (for triggering reactive updates) registeredTabs: [] }; }, 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: (_watch$i = {}, _defineProperty(_watch$i, MODEL_PROP_NAME$i, function (newValue, oldValue) { if (newValue !== oldValue) { newValue = toInteger(newValue, -1); oldValue = toInteger(oldValue, 0); var $tab = this.tabs[newValue]; if ($tab && !$tab.disabled) { this.activateTab($tab); } else { // Try next or prev tabs if (newValue < oldValue) { this.previousTab(); } else { this.nextTab(); } } } }), _defineProperty(_watch$i, "currentTab", function currentTab(newValue) { var index = -1; // Ensure only one tab is active at most this.tabs.forEach(function ($tab, i) { if (i === newValue && !$tab.disabled) { $tab.localActive = true; index = i; } else { $tab.localActive = false; } }); // Update the v-model this.$emit(MODEL_EVENT_NAME$i, index); }), _defineProperty(_watch$i, "tabs", function tabs(newValue, oldValue) { var _this = this; // We use `_uid` instead of `safeId()`, as the later is changed in a `$nextTick()` // if no explicit ID is provided, causing duplicate emits if (!looseEqual(newValue.map(function ($tab) { return $tab[COMPONENT_UID_KEY]; }), oldValue.map(function ($tab) { return $tab[COMPONENT_UID_KEY]; }))) { // 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 _this.$emit(EVENT_NAME_CHANGED, newValue.slice(), oldValue.slice()); }); } }), _defineProperty(_watch$i, "registeredTabs", function registeredTabs() { this.updateTabs(); }), _watch$i), created: function created() { // Create private non-reactive props this.$_observer = null; }, mounted: function mounted() { this.setObserver(true); }, beforeDestroy: function beforeDestroy() { this.setObserver(false); // Ensure no references to child instances exist this.tabs = []; }, methods: { registerTab: function registerTab($tab) { if (!arrayIncludes(this.registeredTabs, $tab)) { this.registeredTabs.push($tab); } }, unregisterTab: function unregisterTab($tab) { this.registeredTabs = this.registeredTabs.slice().filter(function ($t) { return $t !== $tab; }); }, // DOM observer is needed to detect changes in order of tabs setObserver: function setObserver() { var _this2 = this; var on = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; this.$_observer && this.$_observer.disconnect(); this.$_observer = null; if (on) { /* istanbul ignore next: difficult to test mutation observer in JSDOM */ var handler = function handler() { _this2.$nextTick(function () { requestAF(function () { _this2.updateTabs(); }); }); }; // Watch for changes to `<b-tab>` sub components this.$_observer = observeDom(this.$refs.content, handler, { childList: true, subtree: false, attributes: true, attributeFilter: ['id'] }); } }, getTabs: function getTabs() { var $tabs = this.registeredTabs.filter(function ($tab) { return $tab.$children.filter(function ($t) { return $t._isTab; }).length === 0; }); // DOM Order of Tabs var order = []; /* istanbul ignore next: too difficult to test */ if (IS_BROWSER && $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()); }); }, updateTabs: function updateTabs() { 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)); } // Ensure only one tab is active at a time $tabs.forEach(function ($tab, index) { $tab.localActive = index === tabIndex; }); this.tabs = $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 currentTab = this.currentTab, $tabs = this.tabs; var result = false; if ($tab) { var index = $tabs.indexOf($tab); if (index !== currentTab && index > -1 && !$tab.disabled) { var tabEvent = new BvEvent(EVENT_NAME_ACTIVATE_TAB, { cancelable: true, vueTarget: this, componentId: this.safeId() }); this.$emit(tabEvent.type, index, currentTab, tabEvent); if (!tabEvent.defaultPrevented) { this.currentTab = index; result = true; } } } // Couldn't set tab, so ensure v-model is up to date /* istanbul ignore next: should rarely happen */ if (!result && this[MODEL_PROP_NAME$i] !== currentTab) { this.$emit(MODEL_EVENT_NAME$i, 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 _this3 = this; // Wrap in `$nextTick()` to ensure DOM has completed rendering this.$nextTick(function () { attemptFocus(_this3.getButtonForTab($tab)); }); }, // Emit a click event on a specified `<b-tab>` component instance emitTabClick: function emitTabClick(tab, event) { if (isEvent(event) && tab && tab.$emit && !tab.disabled) { tab.$emit(EVENT_NAME_CLICK, event); } }, // Click handler clickTab: function clickTab($tab, event) { this.activateTab($tab); this.emitTabClick($tab, event); }, // 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 = mathMax(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 = mathMax(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 _this4 = this; var align = this.align, card = this.card, end = this.end, fill = this.fill, firstTab = this.firstTab, justified = this.justified, lastTab = this.lastTab, nextTab = this.nextTab, noKeyNav = this.noKeyNav, noNavStyle = this.noNavStyle, pills = this.pills, previousTab = this.previousTab, small = this.small, $tabs = this.tabs, vertical = this.vertical; // 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 _on; var safeId = $tab.safeId; // Ensure at least one tab button is focusable when keynav enabled (if possible) var tabIndex = null; if (!noKeyNav) { // Buttons are not in tab index unless active, or a fallback tab tabIndex = -1; if ($tab === $activeTab || !$activeTab && $tab === $fallbackTab) { // Place tab button in tab sequence tabIndex = null; } } return h(BVTabButton, { props: { controls: safeId ? safeId() : null, id: $tab.controlledBy || (safeId ? safeId("_BV_tab_button_") : null), noKeyNav: noKeyNav, posInSet: index + 1, setSize: $tabs.length, tab: $tab, tabIndex: tabIndex }, on: (_on = {}, _defineProperty(_on, EVENT_NAME_CLICK, function (event) { _this4.clickTab($tab, event); }), _defineProperty(_on, EVENT_NAME_FIRST, firstTab), _defineProperty(_on, EVENT_NAME_PREV, previousTab), _defineProperty(_on, EVENT_NAME_NEXT, nextTab), _defineProperty(_on, EVENT_NAME_LAST, lastTab), _on), key: $tab[COMPONENT_UID_KEY] || index, ref: 'buttons', // Needed to make `this.$refs.buttons` an array refInFor: true }); }); var $nav = h(BNav, { class: this.localNavClass, attrs: { role: 'tablist', id: this.safeId('_BV_tab_controls_') }, props: { fill: fill, justified: justified, align: align, tabs: !noNavStyle && !pills, pills: !noNavStyle && pills, vertical: vertical, small: small, cardHeader: card && !vertical }, ref: 'nav' }, [this.normalizeSlot(SLOT_NAME_TABS_START) || h(), $buttons, this.normalizeSlot(SLOT_NAME_TABS_END) || h()]); $nav = h('div', { class: [{ 'card-header': card && !vertical && !end, 'card-footer': card && !vertical && end, 'col-auto': vertical }, this.navWrapperClass], key: 'bv-tabs-nav' }, [$nav]); var $children = this.normalizeSlot() || []; var $empty = h(); if ($children.length === 0) { $empty = h('div', { class: ['tab-pane', 'active', { 'card-body': card }], key: 'bv-empty-tab' }, this.normalizeSlot(SLOT_NAME_EMPTY)); } var $content = h('div', { staticClass: 'tab-content', class: [{ col: vertical }, this.contentClass], attrs: { id: this.safeId('_BV_tab_container_') }, key: 'bv-content', ref: 'content' }, [$children, $empty]); // Render final output return h(this.tag, { staticClass: 'tabs', class: { row: vertical, 'no-gutters': vertical && card }, attrs: { id: this.safeId() } }, [end ? $content : h(), $nav, end ? h() : $content]); } }); var _objectSpread2$3, _watch$j; var MODEL_PROP_NAME_ACTIVE = 'active'; var MODEL_EVENT_NAME_ACTIVE = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_ACTIVE; // --- Props --- var props$2k = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2({}, props$g), {}, (_objectSpread2$3 = {}, _defineProperty(_objectSpread2$3, MODEL_PROP_NAME_ACTIVE, makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_objectSpread2$3, "buttonId", makeProp(PROP_TYPE_STRING)), _defineProperty(_objectSpread2$3, "disabled", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_objectSpread2$3, "lazy", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_objectSpread2$3, "noBody", makeProp(PROP_TYPE_BOOLEAN, false)), _defineProperty(_objectSpread2$3, "tag", makeProp(PROP_TYPE_STRING, 'div')), _defineProperty(_objectSpread2$3, "title", makeProp(PROP_TYPE_STRING)), _defineProperty(_objectSpread2$3, "titleItemClass", makeProp(PROP_TYPE_ARRAY_OBJECT_STRING)), _defineProperty(_objectSpread2$3, "titleLinkAttributes", makeProp(PROP_TYPE_OBJECT)), _defineProperty(_objectSpread2$3, "titleLinkClass", makeProp(PROP_TYPE_ARRAY_OBJECT_STRING)), _objectSpread2$3))), NAME_TAB); // --- Main component --- // @vue/component var BTab = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TAB, mixins: [idMixin, normalizeSlotMixin], inject: { bvTabs: { default: function _default() { return {}; } } }, props: props$2k, data: function data() { return { localActive: this[MODEL_PROP_NAME_ACTIVE] && !this.disabled }; }, computed: { // For parent sniffing of child _isTab: function _isTab() { return true; }, tabClasses: function tabClasses() { var active = this.localActive, disabled = this.disabled; return [{ active: active, disabled: disabled, 'card-body': this.bvTabs.card && !this.noBody }, // Apply <b-tabs> `activeTabClass` styles when this tab is active active ? 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; } }, watch: (_watch$j = {}, _defineProperty(_watch$j, MODEL_PROP_NAME_ACTIVE, function (newValue, oldValue) { if (newValue !== oldValue) { if (newValue) { // 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(MODEL_EVENT_NAME_ACTIVE, this.localActive); } } } }), _defineProperty(_watch$j, "disabled", function disabled(newValue, oldValue) { if (newValue !== oldValue) { var firstTab = this.bvTabs.firstTab; if (newValue && this.localActive && firstTab) { this.localActive = false; firstTab(); } } }), _defineProperty(_watch$j, "localActive", function localActive(newValue) { // Make `active` prop work with `.sync` modifier this.$emit(MODEL_EVENT_NAME_ACTIVE, newValue); }), _watch$j), mounted: function mounted() { // Inform `<b-tabs>` of our presence this.registerTab(); }, 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 var updateButton = this.bvTabs.updateButton; if (updateButton && this.hasNormalizedSlot(SLOT_NAME_TITLE)) { updateButton(this); } }, beforeDestroy: function beforeDestroy() { // Inform `<b-tabs>` of our departure this.unregisterTab(); }, methods: { // Private methods registerTab: function registerTab() { // Inform `<b-tabs>` of our presence var registerTab = this.bvTabs.registerTab; if (registerTab) { registerTab(this); } }, unregisterTab: function unregisterTab() { // Inform `<b-tabs>` of our departure var unregisterTab = this.bvTabs.unregisterTab; if (unregisterTab) { unregisterTab(this); } }, // Public methods activate: function activate() { // Not inside a `<b-tabs>` component or tab is disabled var activateTab = this.bvTabs.activateTab; return activateTab && !this.disabled ? activateTab(this) : false; }, deactivate: function deactivate() { // Not inside a `<b-tabs>` component or not active to begin with var deactivateTab = this.bvTabs.deactivateTab; return deactivateTab && this.localActive ? deactivateTab(this) : false; } }, render: function render(h) { var localActive = this.localActive; var $content = h(this.tag, { staticClass: 'tab-pane', class: this.tabClasses, directives: [{ name: 'show', value: localActive }], attrs: { role: 'tabpanel', id: this.safeId(), 'aria-hidden': localActive ? 'false' : 'true', 'aria-labelledby': this.controlledBy || null }, ref: 'panel' }, // Render content lazily if requested [localActive || !this.computedLazy ? this.normalizeSlot() : 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(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$1(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__default['default'].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(passengers), order: order }; var keys = Object.keys(this.transports); if (keys.indexOf(to) === -1) { Vue__default['default'].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__default['default'].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__default['default'].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__default['default'].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$1(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$1(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; } }); // @vue/component var DefaultTransition = /*#__PURE__*/Vue__default['default'].extend({ mixins: [normalizeSlotMixin], data: function data() { return { // Transition classes base name name: 'b-toaster' }; }, methods: { onAfterEnter: function onAfterEnter(el) { var _this = this; // Work around a Vue.js bug where `*-enter-to` class is not removed // See: https://github.com/vuejs/vue/pull/7901 // The `*-move` class is also stuck on elements that moved, // but there are no JavaScript hooks to handle after move // See: https://github.com/vuejs/vue/pull/7906 requestAF(function () { removeClass(el, "".concat(_this.name, "-enter-to")); }); } }, render: function render(h) { return h('transition-group', { props: { tag: 'div', name: this.name }, on: { afterEnter: this.onAfterEnter } }, this.normalizeSlot()); } }); // --- Props --- var props$2l = makePropsConfigurable({ // Allowed: 'true' or 'false' or `null` ariaAtomic: makeProp(PROP_TYPE_STRING), ariaLive: makeProp(PROP_TYPE_STRING), name: makeProp(PROP_TYPE_STRING, undefined, true), // Required // Aria role role: makeProp(PROP_TYPE_STRING) }, NAME_TOASTER); // --- Main component --- // @vue/component var BToaster = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TOASTER, mixins: [listenOnRootMixin], props: props$2l, 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; var name = this.name; this.staticName = name; /* istanbul ignore if */ if (wormhole.hasTarget(name)) { warn("A \"<portal-target>\" with name \"".concat(name, "\" already exists in the document."), NAME_TOASTER); this.dead = true; } else { this.doRender = true; this.$once(HOOK_EVENT_NAME_BEFORE_DESTROY, function () { // Let toasts made with `this.$bvToast.toast()` know that this toaster // is being destroyed and should should also destroy/hide themselves _this2.emitOnRoot(getRootEventName(NAME_TOASTER, EVENT_NAME_DESTROYED), name); }); } }, destroyed: function destroyed() { // Remove from DOM if needed var $el = this.$el; /* istanbul ignore next: difficult to test */ if ($el && $el.parentNode) { $el.parentNode.removeChild($el); } }, render: function render(h) { var $toaster = h('div', { class: ['d-none', { 'b-dead-toaster': this.dead }] }); if (this.doRender) { var $target = h(PortalTarget, { staticClass: 'b-toaster-slot', props: { name: this.staticName, multiple: true, tag: 'div', slim: false, // transition: this.transition || DefaultTransition transition: DefaultTransition } }); $toaster = h('div', { staticClass: 'b-toaster', class: [this.staticName], attrs: { id: this.staticName, // Fallback to null to make sure attribute doesn't exist role: this.role || null, 'aria-live': this.ariaLive, 'aria-atomic': this.ariaAtomic } }, [$target]); } return $toaster; } }); var _watch$k; var _makeModelMixin$k = makeModelMixin('visible', { type: PROP_TYPE_BOOLEAN, defaultValue: false, event: EVENT_NAME_CHANGE }), modelMixin$j = _makeModelMixin$k.mixin, modelProps$j = _makeModelMixin$k.props, MODEL_PROP_NAME$j = _makeModelMixin$k.prop, MODEL_EVENT_NAME$j = _makeModelMixin$k.event; var MIN_DURATION = 1000; // --- Props --- var linkProps$7 = pick(props$6, ['href', 'to']); var props$2m = makePropsConfigurable(sortKeys(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, props$g), modelProps$j), linkProps$7), {}, { appendToast: makeProp(PROP_TYPE_BOOLEAN, false), autoHideDelay: makeProp(PROP_TYPE_NUMBER_STRING, 5000), bodyClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), headerClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), // Switches role to 'status' and aria-live to 'polite' isStatus: makeProp(PROP_TYPE_BOOLEAN, false), noAutoHide: makeProp(PROP_TYPE_BOOLEAN, false), noCloseButton: makeProp(PROP_TYPE_BOOLEAN, false), noFade: makeProp(PROP_TYPE_BOOLEAN, false), noHoverPause: makeProp(PROP_TYPE_BOOLEAN, false), solid: makeProp(PROP_TYPE_BOOLEAN, false), // Render the toast in place, rather than in a portal-target static: makeProp(PROP_TYPE_BOOLEAN, false), title: makeProp(PROP_TYPE_STRING), toastClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING), toaster: makeProp(PROP_TYPE_STRING, 'b-toaster-top-right'), variant: makeProp(PROP_TYPE_STRING) })), NAME_TOAST); // --- Main component --- // @vue/component var BToast = /*#__PURE__*/Vue__default['default'].extend({ name: NAME_TOAST, mixins: [attrsMixin, idMixin, modelMixin$j, listenOnRootMixin, normalizeSlotMixin, scopedStyleMixin], inheritAttrs: false, props: props$2m, data: function data() { return { isMounted: false, doRender: false, localShow: false, isTransitioning: false, isHiding: false, order: 0, dismissStarted: 0, resumeDismiss: 0 }; }, computed: { toastClasses: function toastClasses() { var appendToast = this.appendToast, variant = this.variant; return _defineProperty({ 'b-toast-solid': this.solid, 'b-toast-append': appendToast, 'b-toast-prepend': !appendToast }, "b-toast-".concat(variant), variant); }, slotScope: function slotScope() { var hide = this.hide; return { hide: hide }; }, computedDuration: function computedDuration() { // Minimum supported duration is 1 second return mathMax(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 }; }, computedAttrs: function computedAttrs() { return _objectSpread2(_objectSpread2({}, this.bvAttrs), {}, { id: this.safeId(), tabindex: '0' }); } }, watch: (_watch$k = {}, _defineProperty(_watch$k, MODEL_PROP_NAME$j, function (newValue) { this[newValue ? 'show' : 'hide'](); }), _defineProperty(_watch$k, "localShow", function localShow(newValue) { if (newValue !== this[MODEL_PROP_NAME$j]) { this.$emit(MODEL_EVENT_NAME$j, newValue); } }), _defineProperty(_watch$k, "toaster", function toaster() { // If toaster target changed, make sure toaster exists this.$nextTick(this.ensureToaster); }), _defineProperty(_watch$k, "static", function _static(newValue) { // If static changes to true, and the toast is showing, // ensure the toaster target exists if (newValue && this.localShow) { this.ensureToaster(); } }), _watch$k), created: function created() { // Create private non-reactive props this.$_dismissTimer = null; }, mounted: function mounted() { var _this = this; this.isMounted = true; this.$nextTick(function () { if (_this[MODEL_PROP_NAME$j]) { requestAF(function () { _this.show(); }); } }); // Listen for global $root show events this.listenOnRoot(getRootActionEventName(NAME_TOAST, EVENT_NAME_SHOW), function (id) { if (id === _this.safeId()) { _this.show(); } }); // Listen for global $root hide events this.listenOnRoot(getRootActionEventName(NAME_TOAST, EVENT_NAME_HIDE), 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(getRootEventName(NAME_TOASTER, EVENT_NAME_DESTROYED), function (toaster) { /* istanbul ignore next */ if (toaster === _this.computedToaster) { _this.hide(); } }); }, beforeDestroy: function beforeDestroy() { this.clearDismissTimer(); }, methods: { show: function show() { var _this2 = this; if (!this.localShow) { this.ensureToaster(); var showEvt = this.buildEvent(EVENT_NAME_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(EVENT_NAME_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(_objectSpread2({ cancelable: false, target: this.$el || null, relatedTarget: null }, options), {}, { vueTarget: this, componentId: this.safeId() })); }, emitEvent: function emitEvent(bvEvent) { var type = bvEvent.type; this.emitOnRoot(getRootEventName(NAME_TOAST, type), bvEvent); this.$emit(type, bvEvent); }, ensureToaster: function ensureToaster() { if (this.static) { return; } var computedToaster = this.computedToaster; if (!wormhole.hasTarget(computedToaster)) { var div = document.createElement('div'); document.body.appendChild(div); var toaster = new BToaster({ parent: this.$root, propsData: { name: computedToaster } }); toaster.$mount(div); } }, startDismissTimer: function startDismissTimer() { this.clearDismissTimer(); if (!this.noAutoHide) { this.$_dismissTimer = setTimeout(this.hide, this.resumeDismiss || this.computedDuration); this.dismissStarted = Date.now(); this.resumeDismiss = 0; } }, clearDismissTimer: function clearDismissTimer() { clearTimeout(this.$_dismissTimer); this.$_dismissTimer = 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.$_dismissTimer || this.resumeDismiss) { return; } var passed = Date.now() - this.dismissStarted; if (passed > 0) { this.clearDismissTimer(); this.resumeDismiss = mathMax(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(EVENT_NAME_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(EVENT_NAME_HIDDEN); this.emitEvent(hiddenEvt); this.doRender = false; }, // Render helper for generating the toast makeToast: function makeToast(h) { var _this5 = this; var title = this.title, slotScope = this.slotScope; var link = isLink(this); var $headerContent = []; var $title = this.normalizeSlot(SLOT_NAME_TOAST_TITLE, slotScope); if ($title) { $headerContent.push($title); } else if (title) { $headerContent.push(h('strong', { staticClass: 'mr-2' }, title)); } if (!this.noCloseButton) { $headerContent.push(h(BButtonClose, { staticClass: 'ml-auto mb-1', on: { click: function click() { _this5.hide(); } } })); } var $header = h(); if ($headerContent.length > 0) { $header = h('header', { staticClass: 'toast-header', class: this.headerClass }, $headerContent); } var $body = h(link ? BLink : 'div', { staticClass: 'toast-body', class: this.bodyClass, props: link ? pluckProps(linkProps$7, this) : {}, on: link ? { click: this.onLinkClick } : {} }, this.normalizeSlot(SLOT_NAME_DEFAULT, slotScope)); return h('div', { staticClass: 'toast', class: this.toastClass, attrs: this.computedAttrs, key: "toast-".concat(this[COMPONENT_UID_KEY]), ref: 'toast' }, [$header, $body]); } }, render: function render(h) { if (!this.doRender || !this.isMounted) { return h(); } var order = this.order, isStatic = this.static, isHiding = this.isHiding, isStatus = this.isStatus; var name = "b-toast-".concat(this[COMPONENT_UID_KEY]); var $toast = h('div', { staticClass: 'b-toast', class: this.toastClasses, attrs: _objectSpread2(_objectSpread2({}, isStatic ? {} : this.scopedStyleAttrs), {}, { id: this.safeId('_toast_outer'), role: isHiding ? null : isStatus ? 'status' : 'alert', 'aria-live': isHiding ? null : isStatus ? 'polite' : 'assertive', 'aria-atomic': isHiding ? null : 'true' }), key: name, ref: 'b-toast' }, [h(BVTransition, { props: { noFade: this.noFade }, on: this.transitionHandlers }, [this.localShow ? this.makeToast(h) : h()])]); return h(Portal, { props: { name: name, to: this.computedToaster, order: order, slim: true, disabled: isStatic } }, [$toast]); } }); var PROP_NAME$2 = '$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$2m, ['static', 'visible'])))); // Map prop names to toast slot names var propsToSlots$1 = { toastContent: 'default', title: 'toast-title' }; // --- Helper 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 BVToastPop = Vue.extend({ name: NAME_TOAST_POP, extends: BToast, destroyed: function destroyed() { // Make sure we not in document any more var $el = this.$el; if ($el && $el.parentNode) { $el.parentNode.removeChild($el); } }, mounted: function mounted() { var _this = this; // Self destruct handler var handleDestroy = function handleDestroy() { // Ensure the toast has been force hidden _this.localShow = false; _this.doRender = false; _this.$nextTick(function () { _this.$nextTick(function () { // In a `requestAF()` to release control back to application // and to allow the portal-target time to remove the content requestAF(function () { _this.$destroy(); }); }); }); }; // Self destruct if parent destroyed this.$parent.$once(HOOK_EVENT_NAME_DESTROYED, handleDestroy); // Self destruct after hidden this.$once(EVENT_NAME_HIDDEN, handleDestroy); // Self destruct when toaster is destroyed this.listenOnRoot(getRootEventName(NAME_TOASTER, EVENT_NAME_DESTROYED), function (toaster) { /* istanbul ignore next: hard to test */ if (toaster === _this.toaster) { handleDestroy(); } }); } }); // Private method to generate the on-demand toast var makeToast = function makeToast(props, $parent) { if (warnNotClient(PROP_NAME$2)) { /* istanbul ignore next */ return; } // Create an instance of `BVToastPop` component var toast = new BVToastPop({ // 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(_objectSpread2(_objectSpread2({}, filterOptions$1(getComponentConfig(NAME_TOAST))), 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$2)) { /* istanbul ignore next */ return; } makeToast(_objectSpread2(_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(getRootActionEventName(NAME_TOAST, EVENT_NAME_SHOW), 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(getRootActionEventName(NAME_TOAST, EVENT_NAME_HIDE), 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 if (!hasOwnProperty(Vue.prototype, PROP_NAME$2)) { defineProperty(Vue.prototype, PROP_NAME$2, { get: function get() { /* istanbul ignore next */ if (!this || !this[PROP_NAME_PRIV$1]) { warn("\"".concat(PROP_NAME$2, "\" must be accessed from a Vue instance \"this\" context."), NAME_TOAST); } 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 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_TOOLTIP, 'delay', 50), boundary: String(getComponentConfig(NAME_TOOLTIP, 'boundary', 'scrollParent')), boundaryPadding: toInteger(getComponentConfig(NAME_TOOLTIP, 'boundaryPadding', 5), 0), variant: getComponentConfig(NAME_TOOLTIP, 'variant'), customClass: getComponentConfig(NAME_TOOLTIP, '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(_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: toInteger(config.delay, 0), hide: toInteger(config.delay, 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 = toInteger(mod.slice(1), 0); config.delay.show = delay; config.delay.hide = delay; } else if (delayShowRE$1.test(mod)) { // Delay show value config.delay.show = toInteger(mod.slice(2), 0); } else if (delayHideRE$1.test(mod)) { // Delay hide value config.delay.hide = toInteger(mod.slice(2), 0); } else if (offsetRE$1.test(mod)) { // Offset value, negative allowed config.offset = toInteger(mod.slice(1), 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 (!IS_BROWSER) { /* 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(EVENT_NAME_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, AspectPlugin: AspectPlugin, AvatarPlugin: AvatarPlugin, 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, FormRatingPlugin: FormRatingPlugin, 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, OverlayPlugin: OverlayPlugin, PaginationPlugin: PaginationPlugin, PaginationNavPlugin: PaginationNavPlugin, PopoverPlugin: PopoverPlugin, ProgressPlugin: ProgressPlugin, SidebarPlugin: SidebarPlugin, SkeletonPlugin: SkeletonPlugin, 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$1 = 'v-b-scrollspy'; var CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; var CLASS_NAME_ACTIVE = 'active'; var SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'; var SELECTOR_NAV_LINKS = '.nav-link'; var SELECTOR_NAV_ITEMS = '.nav-item'; var SELECTOR_LIST_ITEMS = '.list-group-item'; var SELECTOR_DROPDOWN = '.dropdown, .dropup'; var SELECTOR_DROPDOWN_ITEMS = '.dropdown-item'; var SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; var ROOT_EVENT_NAME_ACTIVATE = getRootEventName('BVScrollspy', 'activate'); var METHOD_OFFSET = 'offset'; var METHOD_POSITION = 'position'; var Default = { element: 'body', offset: 10, method: 'auto', throttle: 75 }; var DefaultType = { element: '(string|element|component)', offset: 'number', method: 'string', throttle: 'number' }; // 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 /* istanbul ignore next */ var typeCheckConfig = function typeCheckConfig(componentName, config, configTypes) /* istanbul ignore next: not easy to test */ { for (var property in configTypes) { if (hasOwnProperty(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 BVScrollSpy /* istanbul ignore next: not easy to test */ = /*#__PURE__*/function () { function BVScrollSpy(element, config, $root) { _classCallCheck(this, BVScrollSpy); // The element we activate links in this.$el = element; this.$scroller = null; this.$selector = [SELECTOR_NAV_LINKS, SELECTOR_LIST_ITEMS, SELECTOR_DROPDOWN_ITEMS].join(','); this.$offsets = []; this.$targets = []; this.$activeTarget = null; this.$scrollHeight = 0; this.$resizeTimeout = null; this.$scrollerObserver = null; this.$targetsObserver = null; this.$root = $root || null; this.$config = null; this.updateConfig(config); } _createClass(BVScrollSpy, [{ 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(_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 (eventName) { eventOn(window, eventName, _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 (eventName) { eventOff(window, eventName, _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 this.$scrollerObserver && this.$scrollerObserver.disconnect(); this.$targetsObserver && this.$targetsObserver.disconnect(); this.$scrollerObserver = null; this.$targetsObserver = null; if (on) { this.$targetsObserver = observeDom(this.$el, function () { _this3.handleEvent('mutation'); }, { subtree: true, childList: true, attributes: true, attributeFilter: ['href'] }); this.$scrollerObserver = 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(event) { var type = isString(event) ? event : event.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.$scrollerObserver) { // 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 ? METHOD_POSITION : METHOD_OFFSET; var method = this.$config.method === 'auto' ? autoMethod : this.$config.method; var methodFn = method === METHOD_POSITION ? position : offset; var offsetBase = method === METHOD_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 && RX_HREF.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(RX_HREF, '$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: toInteger(methodFn(el).top, 0) + offsetBase, target: id }; } return null; }).filter(identity) // 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 || mathMax(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, CLASS_NAME_DROPDOWN_ITEM)) { // This is a dropdown item, so find the .dropdown-toggle and set its state var dropdown = closest(SELECTOR_DROPDOWN, link); if (dropdown) { _this5.setActiveState(select(SELECTOR_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_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_NAV_LIST_GROUP, el); var sibling = el ? el.previousElementSibling : null; if (sibling && matches(sibling, "".concat(SELECTOR_NAV_LINKS, ", ").concat(SELECTOR_LIST_ITEMS))) { _this5.setActiveState(sibling, true); } // Handle special case where nav-link is inside a nav-item if (sibling && matches(sibling, SELECTOR_NAV_ITEMS)) { _this5.setActiveState(select(SELECTOR_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(ROOT_EVENT_NAME_ACTIVATE, target, links); } } }, { key: "clear", value: function clear() { var _this6 = this; selectAll("".concat(this.$selector, ", ").concat(SELECTOR_NAV_ITEMS), this.$el).filter(function (el) { return hasClass(el, CLASS_NAME_ACTIVE); }).forEach(function (el) { return _this6.setActiveState(el, false); }); } }, { key: "setActiveState", value: function setActiveState(el, active) { if (!el) { return; } if (active) { addClass(el, CLASS_NAME_ACTIVE); } else { removeClass(el, CLASS_NAME_ACTIVE); } } }], [{ key: "Name", get: function get() { return NAME$1; } }, { key: "Default", get: function get() { return Default; } }, { key: "DefaultType", get: function get() { return DefaultType; } }]); return BVScrollSpy; }(); 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 = toInteger(mod, 0); } 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 = mathRound(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 !!BVScrollSpy.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 (!IS_BROWSER) { /* 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 BVScrollSpy(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 = { /* istanbul ignore next: not easy to test */ bind: function bind(el, bindings, vnode) { applyScrollspy(el, bindings, vnode); }, /* istanbul ignore next: not easy to test */ inserted: function inserted(el, bindings, vnode) { applyScrollspy(el, bindings, vnode); }, /* istanbul ignore next: not easy to test */ update: function update(el, bindings, vnode) { if (bindings.value !== bindings.oldValue) { applyScrollspy(el, bindings, vnode); } }, /* istanbul ignore next: not easy to test */ componentUpdated: function componentUpdated(el, bindings, vnode) { if (bindings.value !== bindings.oldValue) { applyScrollspy(el, bindings, vnode); } }, /* istanbul ignore next: not easy to test */ unbind: function unbind(el) { removeScrollspy(el); } }; var VBScrollspyPlugin = /*#__PURE__*/pluginFactory({ directives: { VBScrollspy: VBScrollspy } }); 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 NAME$2 = 'BootstrapVue'; // --- BootstrapVue installer --- var install = /*#__PURE__*/installFactory({ plugins: { componentsPlugin: componentsPlugin, directivesPlugin: directivesPlugin } }); // --- BootstrapVue plugin --- var BootstrapVue = /*#__PURE__*/{ install: install, NAME: NAME$2 }; // --- Named exports for BvConfigPlugin --- // Main entry point for the browser build vueUse(BootstrapVue); return BootstrapVue; }))); //# sourceMappingURL=bootstrap-vue.js.map