bootstrap.js (145628B)
1 /*! 2 * Bootstrap v5.2.1 (https://getbootstrap.com/) 3 * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) 4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 5 */ 6 (function (global, factory) { 7 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core')) : 8 typeof define === 'function' && define.amd ? define(['@popperjs/core'], factory) : 9 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory(global.Popper)); 10 })(this, (function (Popper) { 'use strict'; 11 12 function _interopNamespace(e) { 13 if (e && e.__esModule) return e; 14 const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } }); 15 if (e) { 16 for (const k in e) { 17 if (k !== 'default') { 18 const d = Object.getOwnPropertyDescriptor(e, k); 19 Object.defineProperty(n, k, d.get ? d : { 20 enumerable: true, 21 get: () => e[k] 22 }); 23 } 24 } 25 } 26 n.default = e; 27 return Object.freeze(n); 28 } 29 30 const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper); 31 32 /** 33 * -------------------------------------------------------------------------- 34 * Bootstrap (v5.2.1): util/index.js 35 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 36 * -------------------------------------------------------------------------- 37 */ 38 const MAX_UID = 1000000; 39 const MILLISECONDS_MULTIPLIER = 1000; 40 const TRANSITION_END = 'transitionend'; // Shout-out Angus Croll (https://goo.gl/pxwQGp) 41 42 const toType = object => { 43 if (object === null || object === undefined) { 44 return `${object}`; 45 } 46 47 return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); 48 }; 49 /** 50 * Public Util API 51 */ 52 53 54 const getUID = prefix => { 55 do { 56 prefix += Math.floor(Math.random() * MAX_UID); 57 } while (document.getElementById(prefix)); 58 59 return prefix; 60 }; 61 62 const getSelector = element => { 63 let selector = element.getAttribute('data-bs-target'); 64 65 if (!selector || selector === '#') { 66 let hrefAttribute = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, 67 // so everything starting with `#` or `.`. If a "real" URL is used as the selector, 68 // `document.querySelector` will rightfully complain it is invalid. 69 // See https://github.com/twbs/bootstrap/issues/32273 70 71 if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) { 72 return null; 73 } // Just in case some CMS puts out a full URL with the anchor appended 74 75 76 if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { 77 hrefAttribute = `#${hrefAttribute.split('#')[1]}`; 78 } 79 80 selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null; 81 } 82 83 return selector; 84 }; 85 86 const getSelectorFromElement = element => { 87 const selector = getSelector(element); 88 89 if (selector) { 90 return document.querySelector(selector) ? selector : null; 91 } 92 93 return null; 94 }; 95 96 const getElementFromSelector = element => { 97 const selector = getSelector(element); 98 return selector ? document.querySelector(selector) : null; 99 }; 100 101 const getTransitionDurationFromElement = element => { 102 if (!element) { 103 return 0; 104 } // Get transition-duration of the element 105 106 107 let { 108 transitionDuration, 109 transitionDelay 110 } = window.getComputedStyle(element); 111 const floatTransitionDuration = Number.parseFloat(transitionDuration); 112 const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found 113 114 if (!floatTransitionDuration && !floatTransitionDelay) { 115 return 0; 116 } // If multiple durations are defined, take the first 117 118 119 transitionDuration = transitionDuration.split(',')[0]; 120 transitionDelay = transitionDelay.split(',')[0]; 121 return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; 122 }; 123 124 const triggerTransitionEnd = element => { 125 element.dispatchEvent(new Event(TRANSITION_END)); 126 }; 127 128 const isElement = object => { 129 if (!object || typeof object !== 'object') { 130 return false; 131 } 132 133 if (typeof object.jquery !== 'undefined') { 134 object = object[0]; 135 } 136 137 return typeof object.nodeType !== 'undefined'; 138 }; 139 140 const getElement = object => { 141 // it's a jQuery object or a node element 142 if (isElement(object)) { 143 return object.jquery ? object[0] : object; 144 } 145 146 if (typeof object === 'string' && object.length > 0) { 147 return document.querySelector(object); 148 } 149 150 return null; 151 }; 152 153 const isVisible = element => { 154 if (!isElement(element) || element.getClientRects().length === 0) { 155 return false; 156 } 157 158 const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; // Handle `details` element as its content may falsie appear visible when it is closed 159 160 const closedDetails = element.closest('details:not([open])'); 161 162 if (!closedDetails) { 163 return elementIsVisible; 164 } 165 166 if (closedDetails !== element) { 167 const summary = element.closest('summary'); 168 169 if (summary && summary.parentNode !== closedDetails) { 170 return false; 171 } 172 173 if (summary === null) { 174 return false; 175 } 176 } 177 178 return elementIsVisible; 179 }; 180 181 const isDisabled = element => { 182 if (!element || element.nodeType !== Node.ELEMENT_NODE) { 183 return true; 184 } 185 186 if (element.classList.contains('disabled')) { 187 return true; 188 } 189 190 if (typeof element.disabled !== 'undefined') { 191 return element.disabled; 192 } 193 194 return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; 195 }; 196 197 const findShadowRoot = element => { 198 if (!document.documentElement.attachShadow) { 199 return null; 200 } // Can find the shadow root otherwise it'll return the document 201 202 203 if (typeof element.getRootNode === 'function') { 204 const root = element.getRootNode(); 205 return root instanceof ShadowRoot ? root : null; 206 } 207 208 if (element instanceof ShadowRoot) { 209 return element; 210 } // when we don't find a shadow root 211 212 213 if (!element.parentNode) { 214 return null; 215 } 216 217 return findShadowRoot(element.parentNode); 218 }; 219 220 const noop = () => {}; 221 /** 222 * Trick to restart an element's animation 223 * 224 * @param {HTMLElement} element 225 * @return void 226 * 227 * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation 228 */ 229 230 231 const reflow = element => { 232 element.offsetHeight; // eslint-disable-line no-unused-expressions 233 }; 234 235 const getjQuery = () => { 236 if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { 237 return window.jQuery; 238 } 239 240 return null; 241 }; 242 243 const DOMContentLoadedCallbacks = []; 244 245 const onDOMContentLoaded = callback => { 246 if (document.readyState === 'loading') { 247 // add listener on the first call when the document is in loading state 248 if (!DOMContentLoadedCallbacks.length) { 249 document.addEventListener('DOMContentLoaded', () => { 250 for (const callback of DOMContentLoadedCallbacks) { 251 callback(); 252 } 253 }); 254 } 255 256 DOMContentLoadedCallbacks.push(callback); 257 } else { 258 callback(); 259 } 260 }; 261 262 const isRTL = () => document.documentElement.dir === 'rtl'; 263 264 const defineJQueryPlugin = plugin => { 265 onDOMContentLoaded(() => { 266 const $ = getjQuery(); 267 /* istanbul ignore if */ 268 269 if ($) { 270 const name = plugin.NAME; 271 const JQUERY_NO_CONFLICT = $.fn[name]; 272 $.fn[name] = plugin.jQueryInterface; 273 $.fn[name].Constructor = plugin; 274 275 $.fn[name].noConflict = () => { 276 $.fn[name] = JQUERY_NO_CONFLICT; 277 return plugin.jQueryInterface; 278 }; 279 } 280 }); 281 }; 282 283 const execute = callback => { 284 if (typeof callback === 'function') { 285 callback(); 286 } 287 }; 288 289 const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { 290 if (!waitForTransition) { 291 execute(callback); 292 return; 293 } 294 295 const durationPadding = 5; 296 const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; 297 let called = false; 298 299 const handler = ({ 300 target 301 }) => { 302 if (target !== transitionElement) { 303 return; 304 } 305 306 called = true; 307 transitionElement.removeEventListener(TRANSITION_END, handler); 308 execute(callback); 309 }; 310 311 transitionElement.addEventListener(TRANSITION_END, handler); 312 setTimeout(() => { 313 if (!called) { 314 triggerTransitionEnd(transitionElement); 315 } 316 }, emulatedDuration); 317 }; 318 /** 319 * Return the previous/next element of a list. 320 * 321 * @param {array} list The list of elements 322 * @param activeElement The active element 323 * @param shouldGetNext Choose to get next or previous element 324 * @param isCycleAllowed 325 * @return {Element|elem} The proper element 326 */ 327 328 329 const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { 330 const listLength = list.length; 331 let index = list.indexOf(activeElement); // if the element does not exist in the list return an element 332 // depending on the direction and if cycle is allowed 333 334 if (index === -1) { 335 return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]; 336 } 337 338 index += shouldGetNext ? 1 : -1; 339 340 if (isCycleAllowed) { 341 index = (index + listLength) % listLength; 342 } 343 344 return list[Math.max(0, Math.min(index, listLength - 1))]; 345 }; 346 347 /** 348 * -------------------------------------------------------------------------- 349 * Bootstrap (v5.2.1): dom/event-handler.js 350 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 351 * -------------------------------------------------------------------------- 352 */ 353 /** 354 * Constants 355 */ 356 357 const namespaceRegex = /[^.]*(?=\..*)\.|.*/; 358 const stripNameRegex = /\..*/; 359 const stripUidRegex = /::\d+$/; 360 const eventRegistry = {}; // Events storage 361 362 let uidEvent = 1; 363 const customEvents = { 364 mouseenter: 'mouseover', 365 mouseleave: 'mouseout' 366 }; 367 const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']); 368 /** 369 * Private methods 370 */ 371 372 function makeEventUid(element, uid) { 373 return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; 374 } 375 376 function getElementEvents(element) { 377 const uid = makeEventUid(element); 378 element.uidEvent = uid; 379 eventRegistry[uid] = eventRegistry[uid] || {}; 380 return eventRegistry[uid]; 381 } 382 383 function bootstrapHandler(element, fn) { 384 return function handler(event) { 385 hydrateObj(event, { 386 delegateTarget: element 387 }); 388 389 if (handler.oneOff) { 390 EventHandler.off(element, event.type, fn); 391 } 392 393 return fn.apply(element, [event]); 394 }; 395 } 396 397 function bootstrapDelegationHandler(element, selector, fn) { 398 return function handler(event) { 399 const domElements = element.querySelectorAll(selector); 400 401 for (let { 402 target 403 } = event; target && target !== this; target = target.parentNode) { 404 for (const domElement of domElements) { 405 if (domElement !== target) { 406 continue; 407 } 408 409 hydrateObj(event, { 410 delegateTarget: target 411 }); 412 413 if (handler.oneOff) { 414 EventHandler.off(element, event.type, selector, fn); 415 } 416 417 return fn.apply(target, [event]); 418 } 419 } 420 }; 421 } 422 423 function findHandler(events, callable, delegationSelector = null) { 424 return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector); 425 } 426 427 function normalizeParameters(originalTypeEvent, handler, delegationFunction) { 428 const isDelegated = typeof handler === 'string'; // todo: tooltip passes `false` instead of selector, so we need to check 429 430 const callable = isDelegated ? delegationFunction : handler || delegationFunction; 431 let typeEvent = getTypeEvent(originalTypeEvent); 432 433 if (!nativeEvents.has(typeEvent)) { 434 typeEvent = originalTypeEvent; 435 } 436 437 return [isDelegated, callable, typeEvent]; 438 } 439 440 function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { 441 if (typeof originalTypeEvent !== 'string' || !element) { 442 return; 443 } 444 445 let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position 446 // this prevents the handler from being dispatched the same way as mouseover or mouseout does 447 448 if (originalTypeEvent in customEvents) { 449 const wrapFunction = fn => { 450 return function (event) { 451 if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) { 452 return fn.call(this, event); 453 } 454 }; 455 }; 456 457 callable = wrapFunction(callable); 458 } 459 460 const events = getElementEvents(element); 461 const handlers = events[typeEvent] || (events[typeEvent] = {}); 462 const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null); 463 464 if (previousFunction) { 465 previousFunction.oneOff = previousFunction.oneOff && oneOff; 466 return; 467 } 468 469 const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')); 470 const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable); 471 fn.delegationSelector = isDelegated ? handler : null; 472 fn.callable = callable; 473 fn.oneOff = oneOff; 474 fn.uidEvent = uid; 475 handlers[uid] = fn; 476 element.addEventListener(typeEvent, fn, isDelegated); 477 } 478 479 function removeHandler(element, events, typeEvent, handler, delegationSelector) { 480 const fn = findHandler(events[typeEvent], handler, delegationSelector); 481 482 if (!fn) { 483 return; 484 } 485 486 element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)); 487 delete events[typeEvent][fn.uidEvent]; 488 } 489 490 function removeNamespacedHandlers(element, events, typeEvent, namespace) { 491 const storeElementEvent = events[typeEvent] || {}; 492 493 for (const handlerKey of Object.keys(storeElementEvent)) { 494 if (handlerKey.includes(namespace)) { 495 const event = storeElementEvent[handlerKey]; 496 removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); 497 } 498 } 499 } 500 501 function getTypeEvent(event) { 502 // allow to get the native events from namespaced events ('click.bs.button' --> 'click') 503 event = event.replace(stripNameRegex, ''); 504 return customEvents[event] || event; 505 } 506 507 const EventHandler = { 508 on(element, event, handler, delegationFunction) { 509 addHandler(element, event, handler, delegationFunction, false); 510 }, 511 512 one(element, event, handler, delegationFunction) { 513 addHandler(element, event, handler, delegationFunction, true); 514 }, 515 516 off(element, originalTypeEvent, handler, delegationFunction) { 517 if (typeof originalTypeEvent !== 'string' || !element) { 518 return; 519 } 520 521 const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); 522 const inNamespace = typeEvent !== originalTypeEvent; 523 const events = getElementEvents(element); 524 const storeElementEvent = events[typeEvent] || {}; 525 const isNamespace = originalTypeEvent.startsWith('.'); 526 527 if (typeof callable !== 'undefined') { 528 // Simplest case: handler is passed, remove that listener ONLY. 529 if (!Object.keys(storeElementEvent).length) { 530 return; 531 } 532 533 removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null); 534 return; 535 } 536 537 if (isNamespace) { 538 for (const elementEvent of Object.keys(events)) { 539 removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); 540 } 541 } 542 543 for (const keyHandlers of Object.keys(storeElementEvent)) { 544 const handlerKey = keyHandlers.replace(stripUidRegex, ''); 545 546 if (!inNamespace || originalTypeEvent.includes(handlerKey)) { 547 const event = storeElementEvent[keyHandlers]; 548 removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); 549 } 550 } 551 }, 552 553 trigger(element, event, args) { 554 if (typeof event !== 'string' || !element) { 555 return null; 556 } 557 558 const $ = getjQuery(); 559 const typeEvent = getTypeEvent(event); 560 const inNamespace = event !== typeEvent; 561 let jQueryEvent = null; 562 let bubbles = true; 563 let nativeDispatch = true; 564 let defaultPrevented = false; 565 566 if (inNamespace && $) { 567 jQueryEvent = $.Event(event, args); 568 $(element).trigger(jQueryEvent); 569 bubbles = !jQueryEvent.isPropagationStopped(); 570 nativeDispatch = !jQueryEvent.isImmediatePropagationStopped(); 571 defaultPrevented = jQueryEvent.isDefaultPrevented(); 572 } 573 574 let evt = new Event(event, { 575 bubbles, 576 cancelable: true 577 }); 578 evt = hydrateObj(evt, args); 579 580 if (defaultPrevented) { 581 evt.preventDefault(); 582 } 583 584 if (nativeDispatch) { 585 element.dispatchEvent(evt); 586 } 587 588 if (evt.defaultPrevented && jQueryEvent) { 589 jQueryEvent.preventDefault(); 590 } 591 592 return evt; 593 } 594 595 }; 596 597 function hydrateObj(obj, meta) { 598 for (const [key, value] of Object.entries(meta || {})) { 599 try { 600 obj[key] = value; 601 } catch (_unused) { 602 Object.defineProperty(obj, key, { 603 configurable: true, 604 605 get() { 606 return value; 607 } 608 609 }); 610 } 611 } 612 613 return obj; 614 } 615 616 /** 617 * -------------------------------------------------------------------------- 618 * Bootstrap (v5.2.1): dom/data.js 619 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 620 * -------------------------------------------------------------------------- 621 */ 622 623 /** 624 * Constants 625 */ 626 const elementMap = new Map(); 627 const Data = { 628 set(element, key, instance) { 629 if (!elementMap.has(element)) { 630 elementMap.set(element, new Map()); 631 } 632 633 const instanceMap = elementMap.get(element); // make it clear we only want one instance per element 634 // can be removed later when multiple key/instances are fine to be used 635 636 if (!instanceMap.has(key) && instanceMap.size !== 0) { 637 // eslint-disable-next-line no-console 638 console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`); 639 return; 640 } 641 642 instanceMap.set(key, instance); 643 }, 644 645 get(element, key) { 646 if (elementMap.has(element)) { 647 return elementMap.get(element).get(key) || null; 648 } 649 650 return null; 651 }, 652 653 remove(element, key) { 654 if (!elementMap.has(element)) { 655 return; 656 } 657 658 const instanceMap = elementMap.get(element); 659 instanceMap.delete(key); // free up element references if there are no instances left for an element 660 661 if (instanceMap.size === 0) { 662 elementMap.delete(element); 663 } 664 } 665 666 }; 667 668 /** 669 * -------------------------------------------------------------------------- 670 * Bootstrap (v5.2.1): dom/manipulator.js 671 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 672 * -------------------------------------------------------------------------- 673 */ 674 function normalizeData(value) { 675 if (value === 'true') { 676 return true; 677 } 678 679 if (value === 'false') { 680 return false; 681 } 682 683 if (value === Number(value).toString()) { 684 return Number(value); 685 } 686 687 if (value === '' || value === 'null') { 688 return null; 689 } 690 691 if (typeof value !== 'string') { 692 return value; 693 } 694 695 try { 696 return JSON.parse(decodeURIComponent(value)); 697 } catch (_unused) { 698 return value; 699 } 700 } 701 702 function normalizeDataKey(key) { 703 return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`); 704 } 705 706 const Manipulator = { 707 setDataAttribute(element, key, value) { 708 element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); 709 }, 710 711 removeDataAttribute(element, key) { 712 element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); 713 }, 714 715 getDataAttributes(element) { 716 if (!element) { 717 return {}; 718 } 719 720 const attributes = {}; 721 const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig')); 722 723 for (const key of bsKeys) { 724 let pureKey = key.replace(/^bs/, ''); 725 pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length); 726 attributes[pureKey] = normalizeData(element.dataset[key]); 727 } 728 729 return attributes; 730 }, 731 732 getDataAttribute(element, key) { 733 return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); 734 } 735 736 }; 737 738 /** 739 * -------------------------------------------------------------------------- 740 * Bootstrap (v5.2.1): util/config.js 741 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 742 * -------------------------------------------------------------------------- 743 */ 744 /** 745 * Class definition 746 */ 747 748 class Config { 749 // Getters 750 static get Default() { 751 return {}; 752 } 753 754 static get DefaultType() { 755 return {}; 756 } 757 758 static get NAME() { 759 throw new Error('You have to implement the static method "NAME", for each component!'); 760 } 761 762 _getConfig(config) { 763 config = this._mergeConfigObj(config); 764 config = this._configAfterMerge(config); 765 766 this._typeCheckConfig(config); 767 768 return config; 769 } 770 771 _configAfterMerge(config) { 772 return config; 773 } 774 775 _mergeConfigObj(config, element) { 776 const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse 777 778 return { ...this.constructor.Default, 779 ...(typeof jsonConfig === 'object' ? jsonConfig : {}), 780 ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}), 781 ...(typeof config === 'object' ? config : {}) 782 }; 783 } 784 785 _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { 786 for (const property of Object.keys(configTypes)) { 787 const expectedTypes = configTypes[property]; 788 const value = config[property]; 789 const valueType = isElement(value) ? 'element' : toType(value); 790 791 if (!new RegExp(expectedTypes).test(valueType)) { 792 throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); 793 } 794 } 795 } 796 797 } 798 799 /** 800 * -------------------------------------------------------------------------- 801 * Bootstrap (v5.2.1): base-component.js 802 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 803 * -------------------------------------------------------------------------- 804 */ 805 /** 806 * Constants 807 */ 808 809 const VERSION = '5.2.1'; 810 /** 811 * Class definition 812 */ 813 814 class BaseComponent extends Config { 815 constructor(element, config) { 816 super(); 817 element = getElement(element); 818 819 if (!element) { 820 return; 821 } 822 823 this._element = element; 824 this._config = this._getConfig(config); 825 Data.set(this._element, this.constructor.DATA_KEY, this); 826 } // Public 827 828 829 dispose() { 830 Data.remove(this._element, this.constructor.DATA_KEY); 831 EventHandler.off(this._element, this.constructor.EVENT_KEY); 832 833 for (const propertyName of Object.getOwnPropertyNames(this)) { 834 this[propertyName] = null; 835 } 836 } 837 838 _queueCallback(callback, element, isAnimated = true) { 839 executeAfterTransition(callback, element, isAnimated); 840 } 841 842 _getConfig(config) { 843 config = this._mergeConfigObj(config, this._element); 844 config = this._configAfterMerge(config); 845 846 this._typeCheckConfig(config); 847 848 return config; 849 } // Static 850 851 852 static getInstance(element) { 853 return Data.get(getElement(element), this.DATA_KEY); 854 } 855 856 static getOrCreateInstance(element, config = {}) { 857 return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null); 858 } 859 860 static get VERSION() { 861 return VERSION; 862 } 863 864 static get DATA_KEY() { 865 return `bs.${this.NAME}`; 866 } 867 868 static get EVENT_KEY() { 869 return `.${this.DATA_KEY}`; 870 } 871 872 static eventName(name) { 873 return `${name}${this.EVENT_KEY}`; 874 } 875 876 } 877 878 /** 879 * -------------------------------------------------------------------------- 880 * Bootstrap (v5.2.1): util/component-functions.js 881 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 882 * -------------------------------------------------------------------------- 883 */ 884 885 const enableDismissTrigger = (component, method = 'hide') => { 886 const clickEvent = `click.dismiss${component.EVENT_KEY}`; 887 const name = component.NAME; 888 EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { 889 if (['A', 'AREA'].includes(this.tagName)) { 890 event.preventDefault(); 891 } 892 893 if (isDisabled(this)) { 894 return; 895 } 896 897 const target = getElementFromSelector(this) || this.closest(`.${name}`); 898 const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method 899 900 instance[method](); 901 }); 902 }; 903 904 /** 905 * -------------------------------------------------------------------------- 906 * Bootstrap (v5.2.1): alert.js 907 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 908 * -------------------------------------------------------------------------- 909 */ 910 /** 911 * Constants 912 */ 913 914 const NAME$f = 'alert'; 915 const DATA_KEY$a = 'bs.alert'; 916 const EVENT_KEY$b = `.${DATA_KEY$a}`; 917 const EVENT_CLOSE = `close${EVENT_KEY$b}`; 918 const EVENT_CLOSED = `closed${EVENT_KEY$b}`; 919 const CLASS_NAME_FADE$5 = 'fade'; 920 const CLASS_NAME_SHOW$8 = 'show'; 921 /** 922 * Class definition 923 */ 924 925 class Alert extends BaseComponent { 926 // Getters 927 static get NAME() { 928 return NAME$f; 929 } // Public 930 931 932 close() { 933 const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE); 934 935 if (closeEvent.defaultPrevented) { 936 return; 937 } 938 939 this._element.classList.remove(CLASS_NAME_SHOW$8); 940 941 const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5); 942 943 this._queueCallback(() => this._destroyElement(), this._element, isAnimated); 944 } // Private 945 946 947 _destroyElement() { 948 this._element.remove(); 949 950 EventHandler.trigger(this._element, EVENT_CLOSED); 951 this.dispose(); 952 } // Static 953 954 955 static jQueryInterface(config) { 956 return this.each(function () { 957 const data = Alert.getOrCreateInstance(this); 958 959 if (typeof config !== 'string') { 960 return; 961 } 962 963 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { 964 throw new TypeError(`No method named "${config}"`); 965 } 966 967 data[config](this); 968 }); 969 } 970 971 } 972 /** 973 * Data API implementation 974 */ 975 976 977 enableDismissTrigger(Alert, 'close'); 978 /** 979 * jQuery 980 */ 981 982 defineJQueryPlugin(Alert); 983 984 /** 985 * -------------------------------------------------------------------------- 986 * Bootstrap (v5.2.1): button.js 987 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 988 * -------------------------------------------------------------------------- 989 */ 990 /** 991 * Constants 992 */ 993 994 const NAME$e = 'button'; 995 const DATA_KEY$9 = 'bs.button'; 996 const EVENT_KEY$a = `.${DATA_KEY$9}`; 997 const DATA_API_KEY$6 = '.data-api'; 998 const CLASS_NAME_ACTIVE$3 = 'active'; 999 const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]'; 1000 const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`; 1001 /** 1002 * Class definition 1003 */ 1004 1005 class Button extends BaseComponent { 1006 // Getters 1007 static get NAME() { 1008 return NAME$e; 1009 } // Public 1010 1011 1012 toggle() { 1013 // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method 1014 this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3)); 1015 } // Static 1016 1017 1018 static jQueryInterface(config) { 1019 return this.each(function () { 1020 const data = Button.getOrCreateInstance(this); 1021 1022 if (config === 'toggle') { 1023 data[config](); 1024 } 1025 }); 1026 } 1027 1028 } 1029 /** 1030 * Data API implementation 1031 */ 1032 1033 1034 EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => { 1035 event.preventDefault(); 1036 const button = event.target.closest(SELECTOR_DATA_TOGGLE$5); 1037 const data = Button.getOrCreateInstance(button); 1038 data.toggle(); 1039 }); 1040 /** 1041 * jQuery 1042 */ 1043 1044 defineJQueryPlugin(Button); 1045 1046 /** 1047 * -------------------------------------------------------------------------- 1048 * Bootstrap (v5.2.1): dom/selector-engine.js 1049 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 1050 * -------------------------------------------------------------------------- 1051 */ 1052 /** 1053 * Constants 1054 */ 1055 1056 const SelectorEngine = { 1057 find(selector, element = document.documentElement) { 1058 return [].concat(...Element.prototype.querySelectorAll.call(element, selector)); 1059 }, 1060 1061 findOne(selector, element = document.documentElement) { 1062 return Element.prototype.querySelector.call(element, selector); 1063 }, 1064 1065 children(element, selector) { 1066 return [].concat(...element.children).filter(child => child.matches(selector)); 1067 }, 1068 1069 parents(element, selector) { 1070 const parents = []; 1071 let ancestor = element.parentNode.closest(selector); 1072 1073 while (ancestor) { 1074 parents.push(ancestor); 1075 ancestor = ancestor.parentNode.closest(selector); 1076 } 1077 1078 return parents; 1079 }, 1080 1081 prev(element, selector) { 1082 let previous = element.previousElementSibling; 1083 1084 while (previous) { 1085 if (previous.matches(selector)) { 1086 return [previous]; 1087 } 1088 1089 previous = previous.previousElementSibling; 1090 } 1091 1092 return []; 1093 }, 1094 1095 // TODO: this is now unused; remove later along with prev() 1096 next(element, selector) { 1097 let next = element.nextElementSibling; 1098 1099 while (next) { 1100 if (next.matches(selector)) { 1101 return [next]; 1102 } 1103 1104 next = next.nextElementSibling; 1105 } 1106 1107 return []; 1108 }, 1109 1110 focusableChildren(element) { 1111 const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable="true"]'].map(selector => `${selector}:not([tabindex^="-"])`).join(','); 1112 return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)); 1113 } 1114 1115 }; 1116 1117 /** 1118 * -------------------------------------------------------------------------- 1119 * Bootstrap (v5.2.1): util/swipe.js 1120 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 1121 * -------------------------------------------------------------------------- 1122 */ 1123 /** 1124 * Constants 1125 */ 1126 1127 const NAME$d = 'swipe'; 1128 const EVENT_KEY$9 = '.bs.swipe'; 1129 const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`; 1130 const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`; 1131 const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`; 1132 const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`; 1133 const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`; 1134 const POINTER_TYPE_TOUCH = 'touch'; 1135 const POINTER_TYPE_PEN = 'pen'; 1136 const CLASS_NAME_POINTER_EVENT = 'pointer-event'; 1137 const SWIPE_THRESHOLD = 40; 1138 const Default$c = { 1139 endCallback: null, 1140 leftCallback: null, 1141 rightCallback: null 1142 }; 1143 const DefaultType$c = { 1144 endCallback: '(function|null)', 1145 leftCallback: '(function|null)', 1146 rightCallback: '(function|null)' 1147 }; 1148 /** 1149 * Class definition 1150 */ 1151 1152 class Swipe extends Config { 1153 constructor(element, config) { 1154 super(); 1155 this._element = element; 1156 1157 if (!element || !Swipe.isSupported()) { 1158 return; 1159 } 1160 1161 this._config = this._getConfig(config); 1162 this._deltaX = 0; 1163 this._supportPointerEvents = Boolean(window.PointerEvent); 1164 1165 this._initEvents(); 1166 } // Getters 1167 1168 1169 static get Default() { 1170 return Default$c; 1171 } 1172 1173 static get DefaultType() { 1174 return DefaultType$c; 1175 } 1176 1177 static get NAME() { 1178 return NAME$d; 1179 } // Public 1180 1181 1182 dispose() { 1183 EventHandler.off(this._element, EVENT_KEY$9); 1184 } // Private 1185 1186 1187 _start(event) { 1188 if (!this._supportPointerEvents) { 1189 this._deltaX = event.touches[0].clientX; 1190 return; 1191 } 1192 1193 if (this._eventIsPointerPenTouch(event)) { 1194 this._deltaX = event.clientX; 1195 } 1196 } 1197 1198 _end(event) { 1199 if (this._eventIsPointerPenTouch(event)) { 1200 this._deltaX = event.clientX - this._deltaX; 1201 } 1202 1203 this._handleSwipe(); 1204 1205 execute(this._config.endCallback); 1206 } 1207 1208 _move(event) { 1209 this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX; 1210 } 1211 1212 _handleSwipe() { 1213 const absDeltaX = Math.abs(this._deltaX); 1214 1215 if (absDeltaX <= SWIPE_THRESHOLD) { 1216 return; 1217 } 1218 1219 const direction = absDeltaX / this._deltaX; 1220 this._deltaX = 0; 1221 1222 if (!direction) { 1223 return; 1224 } 1225 1226 execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback); 1227 } 1228 1229 _initEvents() { 1230 if (this._supportPointerEvents) { 1231 EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event)); 1232 EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event)); 1233 1234 this._element.classList.add(CLASS_NAME_POINTER_EVENT); 1235 } else { 1236 EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event)); 1237 EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event)); 1238 EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event)); 1239 } 1240 } 1241 1242 _eventIsPointerPenTouch(event) { 1243 return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH); 1244 } // Static 1245 1246 1247 static isSupported() { 1248 return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; 1249 } 1250 1251 } 1252 1253 /** 1254 * -------------------------------------------------------------------------- 1255 * Bootstrap (v5.2.1): carousel.js 1256 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 1257 * -------------------------------------------------------------------------- 1258 */ 1259 /** 1260 * Constants 1261 */ 1262 1263 const NAME$c = 'carousel'; 1264 const DATA_KEY$8 = 'bs.carousel'; 1265 const EVENT_KEY$8 = `.${DATA_KEY$8}`; 1266 const DATA_API_KEY$5 = '.data-api'; 1267 const ARROW_LEFT_KEY$1 = 'ArrowLeft'; 1268 const ARROW_RIGHT_KEY$1 = 'ArrowRight'; 1269 const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch 1270 1271 const ORDER_NEXT = 'next'; 1272 const ORDER_PREV = 'prev'; 1273 const DIRECTION_LEFT = 'left'; 1274 const DIRECTION_RIGHT = 'right'; 1275 const EVENT_SLIDE = `slide${EVENT_KEY$8}`; 1276 const EVENT_SLID = `slid${EVENT_KEY$8}`; 1277 const EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`; 1278 const EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`; 1279 const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`; 1280 const EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`; 1281 const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`; 1282 const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`; 1283 const CLASS_NAME_CAROUSEL = 'carousel'; 1284 const CLASS_NAME_ACTIVE$2 = 'active'; 1285 const CLASS_NAME_SLIDE = 'slide'; 1286 const CLASS_NAME_END = 'carousel-item-end'; 1287 const CLASS_NAME_START = 'carousel-item-start'; 1288 const CLASS_NAME_NEXT = 'carousel-item-next'; 1289 const CLASS_NAME_PREV = 'carousel-item-prev'; 1290 const SELECTOR_ACTIVE = '.active'; 1291 const SELECTOR_ITEM = '.carousel-item'; 1292 const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM; 1293 const SELECTOR_ITEM_IMG = '.carousel-item img'; 1294 const SELECTOR_INDICATORS = '.carousel-indicators'; 1295 const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'; 1296 const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'; 1297 const KEY_TO_DIRECTION = { 1298 [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT, 1299 [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT 1300 }; 1301 const Default$b = { 1302 interval: 5000, 1303 keyboard: true, 1304 pause: 'hover', 1305 ride: false, 1306 touch: true, 1307 wrap: true 1308 }; 1309 const DefaultType$b = { 1310 interval: '(number|boolean)', 1311 // TODO:v6 remove boolean support 1312 keyboard: 'boolean', 1313 pause: '(string|boolean)', 1314 ride: '(boolean|string)', 1315 touch: 'boolean', 1316 wrap: 'boolean' 1317 }; 1318 /** 1319 * Class definition 1320 */ 1321 1322 class Carousel extends BaseComponent { 1323 constructor(element, config) { 1324 super(element, config); 1325 this._interval = null; 1326 this._activeElement = null; 1327 this._isSliding = false; 1328 this.touchTimeout = null; 1329 this._swipeHelper = null; 1330 this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); 1331 1332 this._addEventListeners(); 1333 1334 if (this._config.ride === CLASS_NAME_CAROUSEL) { 1335 this.cycle(); 1336 } 1337 } // Getters 1338 1339 1340 static get Default() { 1341 return Default$b; 1342 } 1343 1344 static get DefaultType() { 1345 return DefaultType$b; 1346 } 1347 1348 static get NAME() { 1349 return NAME$c; 1350 } // Public 1351 1352 1353 next() { 1354 this._slide(ORDER_NEXT); 1355 } 1356 1357 nextWhenVisible() { 1358 // FIXME TODO use `document.visibilityState` 1359 // Don't call next when the page isn't visible 1360 // or the carousel or its parent isn't visible 1361 if (!document.hidden && isVisible(this._element)) { 1362 this.next(); 1363 } 1364 } 1365 1366 prev() { 1367 this._slide(ORDER_PREV); 1368 } 1369 1370 pause() { 1371 if (this._isSliding) { 1372 triggerTransitionEnd(this._element); 1373 } 1374 1375 this._clearInterval(); 1376 } 1377 1378 cycle() { 1379 this._clearInterval(); 1380 1381 this._updateInterval(); 1382 1383 this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval); 1384 } 1385 1386 _maybeEnableCycle() { 1387 if (!this._config.ride) { 1388 return; 1389 } 1390 1391 if (this._isSliding) { 1392 EventHandler.one(this._element, EVENT_SLID, () => this.cycle()); 1393 return; 1394 } 1395 1396 this.cycle(); 1397 } 1398 1399 to(index) { 1400 const items = this._getItems(); 1401 1402 if (index > items.length - 1 || index < 0) { 1403 return; 1404 } 1405 1406 if (this._isSliding) { 1407 EventHandler.one(this._element, EVENT_SLID, () => this.to(index)); 1408 return; 1409 } 1410 1411 const activeIndex = this._getItemIndex(this._getActive()); 1412 1413 if (activeIndex === index) { 1414 return; 1415 } 1416 1417 const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV; 1418 1419 this._slide(order, items[index]); 1420 } 1421 1422 dispose() { 1423 if (this._swipeHelper) { 1424 this._swipeHelper.dispose(); 1425 } 1426 1427 super.dispose(); 1428 } // Private 1429 1430 1431 _configAfterMerge(config) { 1432 config.defaultInterval = config.interval; 1433 return config; 1434 } 1435 1436 _addEventListeners() { 1437 if (this._config.keyboard) { 1438 EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event)); 1439 } 1440 1441 if (this._config.pause === 'hover') { 1442 EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause()); 1443 EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle()); 1444 } 1445 1446 if (this._config.touch && Swipe.isSupported()) { 1447 this._addTouchEventListeners(); 1448 } 1449 } 1450 1451 _addTouchEventListeners() { 1452 for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) { 1453 EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault()); 1454 } 1455 1456 const endCallBack = () => { 1457 if (this._config.pause !== 'hover') { 1458 return; 1459 } // If it's a touch-enabled device, mouseenter/leave are fired as 1460 // part of the mouse compatibility events on first tap - the carousel 1461 // would stop cycling until user tapped out of it; 1462 // here, we listen for touchend, explicitly pause the carousel 1463 // (as if it's the second time we tap on it, mouseenter compat event 1464 // is NOT fired) and after a timeout (to allow for mouse compatibility 1465 // events to fire) we explicitly restart cycling 1466 1467 1468 this.pause(); 1469 1470 if (this.touchTimeout) { 1471 clearTimeout(this.touchTimeout); 1472 } 1473 1474 this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval); 1475 }; 1476 1477 const swipeConfig = { 1478 leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)), 1479 rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)), 1480 endCallback: endCallBack 1481 }; 1482 this._swipeHelper = new Swipe(this._element, swipeConfig); 1483 } 1484 1485 _keydown(event) { 1486 if (/input|textarea/i.test(event.target.tagName)) { 1487 return; 1488 } 1489 1490 const direction = KEY_TO_DIRECTION[event.key]; 1491 1492 if (direction) { 1493 event.preventDefault(); 1494 1495 this._slide(this._directionToOrder(direction)); 1496 } 1497 } 1498 1499 _getItemIndex(element) { 1500 return this._getItems().indexOf(element); 1501 } 1502 1503 _setActiveIndicatorElement(index) { 1504 if (!this._indicatorsElement) { 1505 return; 1506 } 1507 1508 const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement); 1509 activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2); 1510 activeIndicator.removeAttribute('aria-current'); 1511 const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement); 1512 1513 if (newActiveIndicator) { 1514 newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2); 1515 newActiveIndicator.setAttribute('aria-current', 'true'); 1516 } 1517 } 1518 1519 _updateInterval() { 1520 const element = this._activeElement || this._getActive(); 1521 1522 if (!element) { 1523 return; 1524 } 1525 1526 const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10); 1527 this._config.interval = elementInterval || this._config.defaultInterval; 1528 } 1529 1530 _slide(order, element = null) { 1531 if (this._isSliding) { 1532 return; 1533 } 1534 1535 const activeElement = this._getActive(); 1536 1537 const isNext = order === ORDER_NEXT; 1538 const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap); 1539 1540 if (nextElement === activeElement) { 1541 return; 1542 } 1543 1544 const nextElementIndex = this._getItemIndex(nextElement); 1545 1546 const triggerEvent = eventName => { 1547 return EventHandler.trigger(this._element, eventName, { 1548 relatedTarget: nextElement, 1549 direction: this._orderToDirection(order), 1550 from: this._getItemIndex(activeElement), 1551 to: nextElementIndex 1552 }); 1553 }; 1554 1555 const slideEvent = triggerEvent(EVENT_SLIDE); 1556 1557 if (slideEvent.defaultPrevented) { 1558 return; 1559 } 1560 1561 if (!activeElement || !nextElement) { 1562 // Some weirdness is happening, so we bail 1563 // todo: change tests that use empty divs to avoid this check 1564 return; 1565 } 1566 1567 const isCycling = Boolean(this._interval); 1568 this.pause(); 1569 this._isSliding = true; 1570 1571 this._setActiveIndicatorElement(nextElementIndex); 1572 1573 this._activeElement = nextElement; 1574 const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END; 1575 const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV; 1576 nextElement.classList.add(orderClassName); 1577 reflow(nextElement); 1578 activeElement.classList.add(directionalClassName); 1579 nextElement.classList.add(directionalClassName); 1580 1581 const completeCallBack = () => { 1582 nextElement.classList.remove(directionalClassName, orderClassName); 1583 nextElement.classList.add(CLASS_NAME_ACTIVE$2); 1584 activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName); 1585 this._isSliding = false; 1586 triggerEvent(EVENT_SLID); 1587 }; 1588 1589 this._queueCallback(completeCallBack, activeElement, this._isAnimated()); 1590 1591 if (isCycling) { 1592 this.cycle(); 1593 } 1594 } 1595 1596 _isAnimated() { 1597 return this._element.classList.contains(CLASS_NAME_SLIDE); 1598 } 1599 1600 _getActive() { 1601 return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); 1602 } 1603 1604 _getItems() { 1605 return SelectorEngine.find(SELECTOR_ITEM, this._element); 1606 } 1607 1608 _clearInterval() { 1609 if (this._interval) { 1610 clearInterval(this._interval); 1611 this._interval = null; 1612 } 1613 } 1614 1615 _directionToOrder(direction) { 1616 if (isRTL()) { 1617 return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT; 1618 } 1619 1620 return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV; 1621 } 1622 1623 _orderToDirection(order) { 1624 if (isRTL()) { 1625 return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT; 1626 } 1627 1628 return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT; 1629 } // Static 1630 1631 1632 static jQueryInterface(config) { 1633 return this.each(function () { 1634 const data = Carousel.getOrCreateInstance(this, config); 1635 1636 if (typeof config === 'number') { 1637 data.to(config); 1638 return; 1639 } 1640 1641 if (typeof config === 'string') { 1642 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { 1643 throw new TypeError(`No method named "${config}"`); 1644 } 1645 1646 data[config](); 1647 } 1648 }); 1649 } 1650 1651 } 1652 /** 1653 * Data API implementation 1654 */ 1655 1656 1657 EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function (event) { 1658 const target = getElementFromSelector(this); 1659 1660 if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) { 1661 return; 1662 } 1663 1664 event.preventDefault(); 1665 const carousel = Carousel.getOrCreateInstance(target); 1666 const slideIndex = this.getAttribute('data-bs-slide-to'); 1667 1668 if (slideIndex) { 1669 carousel.to(slideIndex); 1670 1671 carousel._maybeEnableCycle(); 1672 1673 return; 1674 } 1675 1676 if (Manipulator.getDataAttribute(this, 'slide') === 'next') { 1677 carousel.next(); 1678 1679 carousel._maybeEnableCycle(); 1680 1681 return; 1682 } 1683 1684 carousel.prev(); 1685 1686 carousel._maybeEnableCycle(); 1687 }); 1688 EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => { 1689 const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); 1690 1691 for (const carousel of carousels) { 1692 Carousel.getOrCreateInstance(carousel); 1693 } 1694 }); 1695 /** 1696 * jQuery 1697 */ 1698 1699 defineJQueryPlugin(Carousel); 1700 1701 /** 1702 * -------------------------------------------------------------------------- 1703 * Bootstrap (v5.2.1): collapse.js 1704 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 1705 * -------------------------------------------------------------------------- 1706 */ 1707 /** 1708 * Constants 1709 */ 1710 1711 const NAME$b = 'collapse'; 1712 const DATA_KEY$7 = 'bs.collapse'; 1713 const EVENT_KEY$7 = `.${DATA_KEY$7}`; 1714 const DATA_API_KEY$4 = '.data-api'; 1715 const EVENT_SHOW$6 = `show${EVENT_KEY$7}`; 1716 const EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`; 1717 const EVENT_HIDE$6 = `hide${EVENT_KEY$7}`; 1718 const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`; 1719 const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`; 1720 const CLASS_NAME_SHOW$7 = 'show'; 1721 const CLASS_NAME_COLLAPSE = 'collapse'; 1722 const CLASS_NAME_COLLAPSING = 'collapsing'; 1723 const CLASS_NAME_COLLAPSED = 'collapsed'; 1724 const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`; 1725 const CLASS_NAME_HORIZONTAL = 'collapse-horizontal'; 1726 const WIDTH = 'width'; 1727 const HEIGHT = 'height'; 1728 const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'; 1729 const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]'; 1730 const Default$a = { 1731 parent: null, 1732 toggle: true 1733 }; 1734 const DefaultType$a = { 1735 parent: '(null|element)', 1736 toggle: 'boolean' 1737 }; 1738 /** 1739 * Class definition 1740 */ 1741 1742 class Collapse extends BaseComponent { 1743 constructor(element, config) { 1744 super(element, config); 1745 this._isTransitioning = false; 1746 this._triggerArray = []; 1747 const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4); 1748 1749 for (const elem of toggleList) { 1750 const selector = getSelectorFromElement(elem); 1751 const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element); 1752 1753 if (selector !== null && filterElement.length) { 1754 this._triggerArray.push(elem); 1755 } 1756 } 1757 1758 this._initializeChildren(); 1759 1760 if (!this._config.parent) { 1761 this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()); 1762 } 1763 1764 if (this._config.toggle) { 1765 this.toggle(); 1766 } 1767 } // Getters 1768 1769 1770 static get Default() { 1771 return Default$a; 1772 } 1773 1774 static get DefaultType() { 1775 return DefaultType$a; 1776 } 1777 1778 static get NAME() { 1779 return NAME$b; 1780 } // Public 1781 1782 1783 toggle() { 1784 if (this._isShown()) { 1785 this.hide(); 1786 } else { 1787 this.show(); 1788 } 1789 } 1790 1791 show() { 1792 if (this._isTransitioning || this._isShown()) { 1793 return; 1794 } 1795 1796 let activeChildren = []; // find active children 1797 1798 if (this._config.parent) { 1799 activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, { 1800 toggle: false 1801 })); 1802 } 1803 1804 if (activeChildren.length && activeChildren[0]._isTransitioning) { 1805 return; 1806 } 1807 1808 const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6); 1809 1810 if (startEvent.defaultPrevented) { 1811 return; 1812 } 1813 1814 for (const activeInstance of activeChildren) { 1815 activeInstance.hide(); 1816 } 1817 1818 const dimension = this._getDimension(); 1819 1820 this._element.classList.remove(CLASS_NAME_COLLAPSE); 1821 1822 this._element.classList.add(CLASS_NAME_COLLAPSING); 1823 1824 this._element.style[dimension] = 0; 1825 1826 this._addAriaAndCollapsedClass(this._triggerArray, true); 1827 1828 this._isTransitioning = true; 1829 1830 const complete = () => { 1831 this._isTransitioning = false; 1832 1833 this._element.classList.remove(CLASS_NAME_COLLAPSING); 1834 1835 this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); 1836 1837 this._element.style[dimension] = ''; 1838 EventHandler.trigger(this._element, EVENT_SHOWN$6); 1839 }; 1840 1841 const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); 1842 const scrollSize = `scroll${capitalizedDimension}`; 1843 1844 this._queueCallback(complete, this._element, true); 1845 1846 this._element.style[dimension] = `${this._element[scrollSize]}px`; 1847 } 1848 1849 hide() { 1850 if (this._isTransitioning || !this._isShown()) { 1851 return; 1852 } 1853 1854 const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6); 1855 1856 if (startEvent.defaultPrevented) { 1857 return; 1858 } 1859 1860 const dimension = this._getDimension(); 1861 1862 this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`; 1863 reflow(this._element); 1864 1865 this._element.classList.add(CLASS_NAME_COLLAPSING); 1866 1867 this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); 1868 1869 for (const trigger of this._triggerArray) { 1870 const element = getElementFromSelector(trigger); 1871 1872 if (element && !this._isShown(element)) { 1873 this._addAriaAndCollapsedClass([trigger], false); 1874 } 1875 } 1876 1877 this._isTransitioning = true; 1878 1879 const complete = () => { 1880 this._isTransitioning = false; 1881 1882 this._element.classList.remove(CLASS_NAME_COLLAPSING); 1883 1884 this._element.classList.add(CLASS_NAME_COLLAPSE); 1885 1886 EventHandler.trigger(this._element, EVENT_HIDDEN$6); 1887 }; 1888 1889 this._element.style[dimension] = ''; 1890 1891 this._queueCallback(complete, this._element, true); 1892 } 1893 1894 _isShown(element = this._element) { 1895 return element.classList.contains(CLASS_NAME_SHOW$7); 1896 } // Private 1897 1898 1899 _configAfterMerge(config) { 1900 config.toggle = Boolean(config.toggle); // Coerce string values 1901 1902 config.parent = getElement(config.parent); 1903 return config; 1904 } 1905 1906 _getDimension() { 1907 return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT; 1908 } 1909 1910 _initializeChildren() { 1911 if (!this._config.parent) { 1912 return; 1913 } 1914 1915 const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4); 1916 1917 for (const element of children) { 1918 const selected = getElementFromSelector(element); 1919 1920 if (selected) { 1921 this._addAriaAndCollapsedClass([element], this._isShown(selected)); 1922 } 1923 } 1924 } 1925 1926 _getFirstLevelChildren(selector) { 1927 const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); // remove children if greater depth 1928 1929 return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element)); 1930 } 1931 1932 _addAriaAndCollapsedClass(triggerArray, isOpen) { 1933 if (!triggerArray.length) { 1934 return; 1935 } 1936 1937 for (const element of triggerArray) { 1938 element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen); 1939 element.setAttribute('aria-expanded', isOpen); 1940 } 1941 } // Static 1942 1943 1944 static jQueryInterface(config) { 1945 const _config = {}; 1946 1947 if (typeof config === 'string' && /show|hide/.test(config)) { 1948 _config.toggle = false; 1949 } 1950 1951 return this.each(function () { 1952 const data = Collapse.getOrCreateInstance(this, _config); 1953 1954 if (typeof config === 'string') { 1955 if (typeof data[config] === 'undefined') { 1956 throw new TypeError(`No method named "${config}"`); 1957 } 1958 1959 data[config](); 1960 } 1961 }); 1962 } 1963 1964 } 1965 /** 1966 * Data API implementation 1967 */ 1968 1969 1970 EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) { 1971 // preventDefault only for <a> elements (which change the URL) not inside the collapsible element 1972 if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') { 1973 event.preventDefault(); 1974 } 1975 1976 const selector = getSelectorFromElement(this); 1977 const selectorElements = SelectorEngine.find(selector); 1978 1979 for (const element of selectorElements) { 1980 Collapse.getOrCreateInstance(element, { 1981 toggle: false 1982 }).toggle(); 1983 } 1984 }); 1985 /** 1986 * jQuery 1987 */ 1988 1989 defineJQueryPlugin(Collapse); 1990 1991 /** 1992 * -------------------------------------------------------------------------- 1993 * Bootstrap (v5.2.1): dropdown.js 1994 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 1995 * -------------------------------------------------------------------------- 1996 */ 1997 /** 1998 * Constants 1999 */ 2000 2001 const NAME$a = 'dropdown'; 2002 const DATA_KEY$6 = 'bs.dropdown'; 2003 const EVENT_KEY$6 = `.${DATA_KEY$6}`; 2004 const DATA_API_KEY$3 = '.data-api'; 2005 const ESCAPE_KEY$2 = 'Escape'; 2006 const TAB_KEY$1 = 'Tab'; 2007 const ARROW_UP_KEY$1 = 'ArrowUp'; 2008 const ARROW_DOWN_KEY$1 = 'ArrowDown'; 2009 const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button 2010 2011 const EVENT_HIDE$5 = `hide${EVENT_KEY$6}`; 2012 const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`; 2013 const EVENT_SHOW$5 = `show${EVENT_KEY$6}`; 2014 const EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`; 2015 const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`; 2016 const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`; 2017 const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`; 2018 const CLASS_NAME_SHOW$6 = 'show'; 2019 const CLASS_NAME_DROPUP = 'dropup'; 2020 const CLASS_NAME_DROPEND = 'dropend'; 2021 const CLASS_NAME_DROPSTART = 'dropstart'; 2022 const CLASS_NAME_DROPUP_CENTER = 'dropup-center'; 2023 const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'; 2024 const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)'; 2025 const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`; 2026 const SELECTOR_MENU = '.dropdown-menu'; 2027 const SELECTOR_NAVBAR = '.navbar'; 2028 const SELECTOR_NAVBAR_NAV = '.navbar-nav'; 2029 const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'; 2030 const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'; 2031 const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'; 2032 const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'; 2033 const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'; 2034 const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'; 2035 const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'; 2036 const PLACEMENT_TOPCENTER = 'top'; 2037 const PLACEMENT_BOTTOMCENTER = 'bottom'; 2038 const Default$9 = { 2039 autoClose: true, 2040 boundary: 'clippingParents', 2041 display: 'dynamic', 2042 offset: [0, 2], 2043 popperConfig: null, 2044 reference: 'toggle' 2045 }; 2046 const DefaultType$9 = { 2047 autoClose: '(boolean|string)', 2048 boundary: '(string|element)', 2049 display: 'string', 2050 offset: '(array|string|function)', 2051 popperConfig: '(null|object|function)', 2052 reference: '(string|element|object)' 2053 }; 2054 /** 2055 * Class definition 2056 */ 2057 2058 class Dropdown extends BaseComponent { 2059 constructor(element, config) { 2060 super(element, config); 2061 this._popper = null; 2062 this._parent = this._element.parentNode; // dropdown wrapper 2063 // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/ 2064 2065 this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0]; 2066 this._inNavbar = this._detectNavbar(); 2067 } // Getters 2068 2069 2070 static get Default() { 2071 return Default$9; 2072 } 2073 2074 static get DefaultType() { 2075 return DefaultType$9; 2076 } 2077 2078 static get NAME() { 2079 return NAME$a; 2080 } // Public 2081 2082 2083 toggle() { 2084 return this._isShown() ? this.hide() : this.show(); 2085 } 2086 2087 show() { 2088 if (isDisabled(this._element) || this._isShown()) { 2089 return; 2090 } 2091 2092 const relatedTarget = { 2093 relatedTarget: this._element 2094 }; 2095 const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget); 2096 2097 if (showEvent.defaultPrevented) { 2098 return; 2099 } 2100 2101 this._createPopper(); // If this is a touch-enabled device we add extra 2102 // empty mouseover listeners to the body's immediate children; 2103 // only needed because of broken event delegation on iOS 2104 // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html 2105 2106 2107 if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) { 2108 for (const element of [].concat(...document.body.children)) { 2109 EventHandler.on(element, 'mouseover', noop); 2110 } 2111 } 2112 2113 this._element.focus(); 2114 2115 this._element.setAttribute('aria-expanded', true); 2116 2117 this._menu.classList.add(CLASS_NAME_SHOW$6); 2118 2119 this._element.classList.add(CLASS_NAME_SHOW$6); 2120 2121 EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget); 2122 } 2123 2124 hide() { 2125 if (isDisabled(this._element) || !this._isShown()) { 2126 return; 2127 } 2128 2129 const relatedTarget = { 2130 relatedTarget: this._element 2131 }; 2132 2133 this._completeHide(relatedTarget); 2134 } 2135 2136 dispose() { 2137 if (this._popper) { 2138 this._popper.destroy(); 2139 } 2140 2141 super.dispose(); 2142 } 2143 2144 update() { 2145 this._inNavbar = this._detectNavbar(); 2146 2147 if (this._popper) { 2148 this._popper.update(); 2149 } 2150 } // Private 2151 2152 2153 _completeHide(relatedTarget) { 2154 const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget); 2155 2156 if (hideEvent.defaultPrevented) { 2157 return; 2158 } // If this is a touch-enabled device we remove the extra 2159 // empty mouseover listeners we added for iOS support 2160 2161 2162 if ('ontouchstart' in document.documentElement) { 2163 for (const element of [].concat(...document.body.children)) { 2164 EventHandler.off(element, 'mouseover', noop); 2165 } 2166 } 2167 2168 if (this._popper) { 2169 this._popper.destroy(); 2170 } 2171 2172 this._menu.classList.remove(CLASS_NAME_SHOW$6); 2173 2174 this._element.classList.remove(CLASS_NAME_SHOW$6); 2175 2176 this._element.setAttribute('aria-expanded', 'false'); 2177 2178 Manipulator.removeDataAttribute(this._menu, 'popper'); 2179 EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget); 2180 } 2181 2182 _getConfig(config) { 2183 config = super._getConfig(config); 2184 2185 if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') { 2186 // Popper virtual elements require a getBoundingClientRect method 2187 throw new TypeError(`${NAME$a.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); 2188 } 2189 2190 return config; 2191 } 2192 2193 _createPopper() { 2194 if (typeof Popper__namespace === 'undefined') { 2195 throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)'); 2196 } 2197 2198 let referenceElement = this._element; 2199 2200 if (this._config.reference === 'parent') { 2201 referenceElement = this._parent; 2202 } else if (isElement(this._config.reference)) { 2203 referenceElement = getElement(this._config.reference); 2204 } else if (typeof this._config.reference === 'object') { 2205 referenceElement = this._config.reference; 2206 } 2207 2208 const popperConfig = this._getPopperConfig(); 2209 2210 this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig); 2211 } 2212 2213 _isShown() { 2214 return this._menu.classList.contains(CLASS_NAME_SHOW$6); 2215 } 2216 2217 _getPlacement() { 2218 const parentDropdown = this._parent; 2219 2220 if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { 2221 return PLACEMENT_RIGHT; 2222 } 2223 2224 if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { 2225 return PLACEMENT_LEFT; 2226 } 2227 2228 if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) { 2229 return PLACEMENT_TOPCENTER; 2230 } 2231 2232 if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) { 2233 return PLACEMENT_BOTTOMCENTER; 2234 } // We need to trim the value because custom properties can also include spaces 2235 2236 2237 const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'; 2238 2239 if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { 2240 return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP; 2241 } 2242 2243 return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM; 2244 } 2245 2246 _detectNavbar() { 2247 return this._element.closest(SELECTOR_NAVBAR) !== null; 2248 } 2249 2250 _getOffset() { 2251 const { 2252 offset 2253 } = this._config; 2254 2255 if (typeof offset === 'string') { 2256 return offset.split(',').map(value => Number.parseInt(value, 10)); 2257 } 2258 2259 if (typeof offset === 'function') { 2260 return popperData => offset(popperData, this._element); 2261 } 2262 2263 return offset; 2264 } 2265 2266 _getPopperConfig() { 2267 const defaultBsPopperConfig = { 2268 placement: this._getPlacement(), 2269 modifiers: [{ 2270 name: 'preventOverflow', 2271 options: { 2272 boundary: this._config.boundary 2273 } 2274 }, { 2275 name: 'offset', 2276 options: { 2277 offset: this._getOffset() 2278 } 2279 }] 2280 }; // Disable Popper if we have a static display or Dropdown is in Navbar 2281 2282 if (this._inNavbar || this._config.display === 'static') { 2283 Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // todo:v6 remove 2284 2285 defaultBsPopperConfig.modifiers = [{ 2286 name: 'applyStyles', 2287 enabled: false 2288 }]; 2289 } 2290 2291 return { ...defaultBsPopperConfig, 2292 ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) 2293 }; 2294 } 2295 2296 _selectMenuItem({ 2297 key, 2298 target 2299 }) { 2300 const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element)); 2301 2302 if (!items.length) { 2303 return; 2304 } // if target isn't included in items (e.g. when expanding the dropdown) 2305 // allow cycling to get the last item in case key equals ARROW_UP_KEY 2306 2307 2308 getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus(); 2309 } // Static 2310 2311 2312 static jQueryInterface(config) { 2313 return this.each(function () { 2314 const data = Dropdown.getOrCreateInstance(this, config); 2315 2316 if (typeof config !== 'string') { 2317 return; 2318 } 2319 2320 if (typeof data[config] === 'undefined') { 2321 throw new TypeError(`No method named "${config}"`); 2322 } 2323 2324 data[config](); 2325 }); 2326 } 2327 2328 static clearMenus(event) { 2329 if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) { 2330 return; 2331 } 2332 2333 const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN); 2334 2335 for (const toggle of openToggles) { 2336 const context = Dropdown.getInstance(toggle); 2337 2338 if (!context || context._config.autoClose === false) { 2339 continue; 2340 } 2341 2342 const composedPath = event.composedPath(); 2343 const isMenuTarget = composedPath.includes(context._menu); 2344 2345 if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) { 2346 continue; 2347 } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu 2348 2349 2350 if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) { 2351 continue; 2352 } 2353 2354 const relatedTarget = { 2355 relatedTarget: context._element 2356 }; 2357 2358 if (event.type === 'click') { 2359 relatedTarget.clickEvent = event; 2360 } 2361 2362 context._completeHide(relatedTarget); 2363 } 2364 } 2365 2366 static dataApiKeydownHandler(event) { 2367 // If not an UP | DOWN | ESCAPE key => not a dropdown command 2368 // If input/textarea && if key is other than ESCAPE => not a dropdown command 2369 const isInput = /input|textarea/i.test(event.target.tagName); 2370 const isEscapeEvent = event.key === ESCAPE_KEY$2; 2371 const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key); 2372 2373 if (!isUpOrDownEvent && !isEscapeEvent) { 2374 return; 2375 } 2376 2377 if (isInput && !isEscapeEvent) { 2378 return; 2379 } 2380 2381 event.preventDefault(); // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/ 2382 2383 const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0]; 2384 const instance = Dropdown.getOrCreateInstance(getToggleButton); 2385 2386 if (isUpOrDownEvent) { 2387 event.stopPropagation(); 2388 instance.show(); 2389 2390 instance._selectMenuItem(event); 2391 2392 return; 2393 } 2394 2395 if (instance._isShown()) { 2396 // else is escape and we check if it is shown 2397 event.stopPropagation(); 2398 instance.hide(); 2399 getToggleButton.focus(); 2400 } 2401 } 2402 2403 } 2404 /** 2405 * Data API implementation 2406 */ 2407 2408 2409 EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler); 2410 EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler); 2411 EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus); 2412 EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); 2413 EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) { 2414 event.preventDefault(); 2415 Dropdown.getOrCreateInstance(this).toggle(); 2416 }); 2417 /** 2418 * jQuery 2419 */ 2420 2421 defineJQueryPlugin(Dropdown); 2422 2423 /** 2424 * -------------------------------------------------------------------------- 2425 * Bootstrap (v5.2.1): util/scrollBar.js 2426 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 2427 * -------------------------------------------------------------------------- 2428 */ 2429 /** 2430 * Constants 2431 */ 2432 2433 const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; 2434 const SELECTOR_STICKY_CONTENT = '.sticky-top'; 2435 const PROPERTY_PADDING = 'padding-right'; 2436 const PROPERTY_MARGIN = 'margin-right'; 2437 /** 2438 * Class definition 2439 */ 2440 2441 class ScrollBarHelper { 2442 constructor() { 2443 this._element = document.body; 2444 } // Public 2445 2446 2447 getWidth() { 2448 // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes 2449 const documentWidth = document.documentElement.clientWidth; 2450 return Math.abs(window.innerWidth - documentWidth); 2451 } 2452 2453 hide() { 2454 const width = this.getWidth(); 2455 2456 this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width 2457 2458 2459 this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth 2460 2461 2462 this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width); 2463 2464 this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width); 2465 } 2466 2467 reset() { 2468 this._resetElementAttributes(this._element, 'overflow'); 2469 2470 this._resetElementAttributes(this._element, PROPERTY_PADDING); 2471 2472 this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING); 2473 2474 this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN); 2475 } 2476 2477 isOverflowing() { 2478 return this.getWidth() > 0; 2479 } // Private 2480 2481 2482 _disableOverFlow() { 2483 this._saveInitialAttribute(this._element, 'overflow'); 2484 2485 this._element.style.overflow = 'hidden'; 2486 } 2487 2488 _setElementAttributes(selector, styleProperty, callback) { 2489 const scrollbarWidth = this.getWidth(); 2490 2491 const manipulationCallBack = element => { 2492 if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { 2493 return; 2494 } 2495 2496 this._saveInitialAttribute(element, styleProperty); 2497 2498 const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty); 2499 element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`); 2500 }; 2501 2502 this._applyManipulationCallback(selector, manipulationCallBack); 2503 } 2504 2505 _saveInitialAttribute(element, styleProperty) { 2506 const actualValue = element.style.getPropertyValue(styleProperty); 2507 2508 if (actualValue) { 2509 Manipulator.setDataAttribute(element, styleProperty, actualValue); 2510 } 2511 } 2512 2513 _resetElementAttributes(selector, styleProperty) { 2514 const manipulationCallBack = element => { 2515 const value = Manipulator.getDataAttribute(element, styleProperty); // We only want to remove the property if the value is `null`; the value can also be zero 2516 2517 if (value === null) { 2518 element.style.removeProperty(styleProperty); 2519 return; 2520 } 2521 2522 Manipulator.removeDataAttribute(element, styleProperty); 2523 element.style.setProperty(styleProperty, value); 2524 }; 2525 2526 this._applyManipulationCallback(selector, manipulationCallBack); 2527 } 2528 2529 _applyManipulationCallback(selector, callBack) { 2530 if (isElement(selector)) { 2531 callBack(selector); 2532 return; 2533 } 2534 2535 for (const sel of SelectorEngine.find(selector, this._element)) { 2536 callBack(sel); 2537 } 2538 } 2539 2540 } 2541 2542 /** 2543 * -------------------------------------------------------------------------- 2544 * Bootstrap (v5.2.1): util/backdrop.js 2545 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 2546 * -------------------------------------------------------------------------- 2547 */ 2548 /** 2549 * Constants 2550 */ 2551 2552 const NAME$9 = 'backdrop'; 2553 const CLASS_NAME_FADE$4 = 'fade'; 2554 const CLASS_NAME_SHOW$5 = 'show'; 2555 const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`; 2556 const Default$8 = { 2557 className: 'modal-backdrop', 2558 clickCallback: null, 2559 isAnimated: false, 2560 isVisible: true, 2561 // if false, we use the backdrop helper without adding any element to the dom 2562 rootElement: 'body' // give the choice to place backdrop under different elements 2563 2564 }; 2565 const DefaultType$8 = { 2566 className: 'string', 2567 clickCallback: '(function|null)', 2568 isAnimated: 'boolean', 2569 isVisible: 'boolean', 2570 rootElement: '(element|string)' 2571 }; 2572 /** 2573 * Class definition 2574 */ 2575 2576 class Backdrop extends Config { 2577 constructor(config) { 2578 super(); 2579 this._config = this._getConfig(config); 2580 this._isAppended = false; 2581 this._element = null; 2582 } // Getters 2583 2584 2585 static get Default() { 2586 return Default$8; 2587 } 2588 2589 static get DefaultType() { 2590 return DefaultType$8; 2591 } 2592 2593 static get NAME() { 2594 return NAME$9; 2595 } // Public 2596 2597 2598 show(callback) { 2599 if (!this._config.isVisible) { 2600 execute(callback); 2601 return; 2602 } 2603 2604 this._append(); 2605 2606 const element = this._getElement(); 2607 2608 if (this._config.isAnimated) { 2609 reflow(element); 2610 } 2611 2612 element.classList.add(CLASS_NAME_SHOW$5); 2613 2614 this._emulateAnimation(() => { 2615 execute(callback); 2616 }); 2617 } 2618 2619 hide(callback) { 2620 if (!this._config.isVisible) { 2621 execute(callback); 2622 return; 2623 } 2624 2625 this._getElement().classList.remove(CLASS_NAME_SHOW$5); 2626 2627 this._emulateAnimation(() => { 2628 this.dispose(); 2629 execute(callback); 2630 }); 2631 } 2632 2633 dispose() { 2634 if (!this._isAppended) { 2635 return; 2636 } 2637 2638 EventHandler.off(this._element, EVENT_MOUSEDOWN); 2639 2640 this._element.remove(); 2641 2642 this._isAppended = false; 2643 } // Private 2644 2645 2646 _getElement() { 2647 if (!this._element) { 2648 const backdrop = document.createElement('div'); 2649 backdrop.className = this._config.className; 2650 2651 if (this._config.isAnimated) { 2652 backdrop.classList.add(CLASS_NAME_FADE$4); 2653 } 2654 2655 this._element = backdrop; 2656 } 2657 2658 return this._element; 2659 } 2660 2661 _configAfterMerge(config) { 2662 // use getElement() with the default "body" to get a fresh Element on each instantiation 2663 config.rootElement = getElement(config.rootElement); 2664 return config; 2665 } 2666 2667 _append() { 2668 if (this._isAppended) { 2669 return; 2670 } 2671 2672 const element = this._getElement(); 2673 2674 this._config.rootElement.append(element); 2675 2676 EventHandler.on(element, EVENT_MOUSEDOWN, () => { 2677 execute(this._config.clickCallback); 2678 }); 2679 this._isAppended = true; 2680 } 2681 2682 _emulateAnimation(callback) { 2683 executeAfterTransition(callback, this._getElement(), this._config.isAnimated); 2684 } 2685 2686 } 2687 2688 /** 2689 * -------------------------------------------------------------------------- 2690 * Bootstrap (v5.2.1): util/focustrap.js 2691 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 2692 * -------------------------------------------------------------------------- 2693 */ 2694 /** 2695 * Constants 2696 */ 2697 2698 const NAME$8 = 'focustrap'; 2699 const DATA_KEY$5 = 'bs.focustrap'; 2700 const EVENT_KEY$5 = `.${DATA_KEY$5}`; 2701 const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`; 2702 const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`; 2703 const TAB_KEY = 'Tab'; 2704 const TAB_NAV_FORWARD = 'forward'; 2705 const TAB_NAV_BACKWARD = 'backward'; 2706 const Default$7 = { 2707 autofocus: true, 2708 trapElement: null // The element to trap focus inside of 2709 2710 }; 2711 const DefaultType$7 = { 2712 autofocus: 'boolean', 2713 trapElement: 'element' 2714 }; 2715 /** 2716 * Class definition 2717 */ 2718 2719 class FocusTrap extends Config { 2720 constructor(config) { 2721 super(); 2722 this._config = this._getConfig(config); 2723 this._isActive = false; 2724 this._lastTabNavDirection = null; 2725 } // Getters 2726 2727 2728 static get Default() { 2729 return Default$7; 2730 } 2731 2732 static get DefaultType() { 2733 return DefaultType$7; 2734 } 2735 2736 static get NAME() { 2737 return NAME$8; 2738 } // Public 2739 2740 2741 activate() { 2742 if (this._isActive) { 2743 return; 2744 } 2745 2746 if (this._config.autofocus) { 2747 this._config.trapElement.focus(); 2748 } 2749 2750 EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop 2751 2752 EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event)); 2753 EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)); 2754 this._isActive = true; 2755 } 2756 2757 deactivate() { 2758 if (!this._isActive) { 2759 return; 2760 } 2761 2762 this._isActive = false; 2763 EventHandler.off(document, EVENT_KEY$5); 2764 } // Private 2765 2766 2767 _handleFocusin(event) { 2768 const { 2769 trapElement 2770 } = this._config; 2771 2772 if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) { 2773 return; 2774 } 2775 2776 const elements = SelectorEngine.focusableChildren(trapElement); 2777 2778 if (elements.length === 0) { 2779 trapElement.focus(); 2780 } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { 2781 elements[elements.length - 1].focus(); 2782 } else { 2783 elements[0].focus(); 2784 } 2785 } 2786 2787 _handleKeydown(event) { 2788 if (event.key !== TAB_KEY) { 2789 return; 2790 } 2791 2792 this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD; 2793 } 2794 2795 } 2796 2797 /** 2798 * -------------------------------------------------------------------------- 2799 * Bootstrap (v5.2.1): modal.js 2800 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 2801 * -------------------------------------------------------------------------- 2802 */ 2803 /** 2804 * Constants 2805 */ 2806 2807 const NAME$7 = 'modal'; 2808 const DATA_KEY$4 = 'bs.modal'; 2809 const EVENT_KEY$4 = `.${DATA_KEY$4}`; 2810 const DATA_API_KEY$2 = '.data-api'; 2811 const ESCAPE_KEY$1 = 'Escape'; 2812 const EVENT_HIDE$4 = `hide${EVENT_KEY$4}`; 2813 const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`; 2814 const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`; 2815 const EVENT_SHOW$4 = `show${EVENT_KEY$4}`; 2816 const EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`; 2817 const EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`; 2818 const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`; 2819 const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`; 2820 const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`; 2821 const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`; 2822 const CLASS_NAME_OPEN = 'modal-open'; 2823 const CLASS_NAME_FADE$3 = 'fade'; 2824 const CLASS_NAME_SHOW$4 = 'show'; 2825 const CLASS_NAME_STATIC = 'modal-static'; 2826 const OPEN_SELECTOR$1 = '.modal.show'; 2827 const SELECTOR_DIALOG = '.modal-dialog'; 2828 const SELECTOR_MODAL_BODY = '.modal-body'; 2829 const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]'; 2830 const Default$6 = { 2831 backdrop: true, 2832 focus: true, 2833 keyboard: true 2834 }; 2835 const DefaultType$6 = { 2836 backdrop: '(boolean|string)', 2837 focus: 'boolean', 2838 keyboard: 'boolean' 2839 }; 2840 /** 2841 * Class definition 2842 */ 2843 2844 class Modal extends BaseComponent { 2845 constructor(element, config) { 2846 super(element, config); 2847 this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); 2848 this._backdrop = this._initializeBackDrop(); 2849 this._focustrap = this._initializeFocusTrap(); 2850 this._isShown = false; 2851 this._isTransitioning = false; 2852 this._scrollBar = new ScrollBarHelper(); 2853 2854 this._addEventListeners(); 2855 } // Getters 2856 2857 2858 static get Default() { 2859 return Default$6; 2860 } 2861 2862 static get DefaultType() { 2863 return DefaultType$6; 2864 } 2865 2866 static get NAME() { 2867 return NAME$7; 2868 } // Public 2869 2870 2871 toggle(relatedTarget) { 2872 return this._isShown ? this.hide() : this.show(relatedTarget); 2873 } 2874 2875 show(relatedTarget) { 2876 if (this._isShown || this._isTransitioning) { 2877 return; 2878 } 2879 2880 const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, { 2881 relatedTarget 2882 }); 2883 2884 if (showEvent.defaultPrevented) { 2885 return; 2886 } 2887 2888 this._isShown = true; 2889 this._isTransitioning = true; 2890 2891 this._scrollBar.hide(); 2892 2893 document.body.classList.add(CLASS_NAME_OPEN); 2894 2895 this._adjustDialog(); 2896 2897 this._backdrop.show(() => this._showElement(relatedTarget)); 2898 } 2899 2900 hide() { 2901 if (!this._isShown || this._isTransitioning) { 2902 return; 2903 } 2904 2905 const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4); 2906 2907 if (hideEvent.defaultPrevented) { 2908 return; 2909 } 2910 2911 this._isShown = false; 2912 this._isTransitioning = true; 2913 2914 this._focustrap.deactivate(); 2915 2916 this._element.classList.remove(CLASS_NAME_SHOW$4); 2917 2918 this._queueCallback(() => this._hideModal(), this._element, this._isAnimated()); 2919 } 2920 2921 dispose() { 2922 for (const htmlElement of [window, this._dialog]) { 2923 EventHandler.off(htmlElement, EVENT_KEY$4); 2924 } 2925 2926 this._backdrop.dispose(); 2927 2928 this._focustrap.deactivate(); 2929 2930 super.dispose(); 2931 } 2932 2933 handleUpdate() { 2934 this._adjustDialog(); 2935 } // Private 2936 2937 2938 _initializeBackDrop() { 2939 return new Backdrop({ 2940 isVisible: Boolean(this._config.backdrop), 2941 // 'static' option will be translated to true, and booleans will keep their value, 2942 isAnimated: this._isAnimated() 2943 }); 2944 } 2945 2946 _initializeFocusTrap() { 2947 return new FocusTrap({ 2948 trapElement: this._element 2949 }); 2950 } 2951 2952 _showElement(relatedTarget) { 2953 // try to append dynamic modal 2954 if (!document.body.contains(this._element)) { 2955 document.body.append(this._element); 2956 } 2957 2958 this._element.style.display = 'block'; 2959 2960 this._element.removeAttribute('aria-hidden'); 2961 2962 this._element.setAttribute('aria-modal', true); 2963 2964 this._element.setAttribute('role', 'dialog'); 2965 2966 this._element.scrollTop = 0; 2967 const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); 2968 2969 if (modalBody) { 2970 modalBody.scrollTop = 0; 2971 } 2972 2973 reflow(this._element); 2974 2975 this._element.classList.add(CLASS_NAME_SHOW$4); 2976 2977 const transitionComplete = () => { 2978 if (this._config.focus) { 2979 this._focustrap.activate(); 2980 } 2981 2982 this._isTransitioning = false; 2983 EventHandler.trigger(this._element, EVENT_SHOWN$4, { 2984 relatedTarget 2985 }); 2986 }; 2987 2988 this._queueCallback(transitionComplete, this._dialog, this._isAnimated()); 2989 } 2990 2991 _addEventListeners() { 2992 EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => { 2993 if (event.key !== ESCAPE_KEY$1) { 2994 return; 2995 } 2996 2997 if (this._config.keyboard) { 2998 event.preventDefault(); 2999 this.hide(); 3000 return; 3001 } 3002 3003 this._triggerBackdropTransition(); 3004 }); 3005 EventHandler.on(window, EVENT_RESIZE$1, () => { 3006 if (this._isShown && !this._isTransitioning) { 3007 this._adjustDialog(); 3008 } 3009 }); 3010 EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => { 3011 EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => { 3012 // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks 3013 if (this._dialog.contains(event.target) || this._dialog.contains(event2.target)) { 3014 return; 3015 } 3016 3017 if (this._config.backdrop === 'static') { 3018 this._triggerBackdropTransition(); 3019 3020 return; 3021 } 3022 3023 if (this._config.backdrop) { 3024 this.hide(); 3025 } 3026 }); 3027 }); 3028 } 3029 3030 _hideModal() { 3031 this._element.style.display = 'none'; 3032 3033 this._element.setAttribute('aria-hidden', true); 3034 3035 this._element.removeAttribute('aria-modal'); 3036 3037 this._element.removeAttribute('role'); 3038 3039 this._isTransitioning = false; 3040 3041 this._backdrop.hide(() => { 3042 document.body.classList.remove(CLASS_NAME_OPEN); 3043 3044 this._resetAdjustments(); 3045 3046 this._scrollBar.reset(); 3047 3048 EventHandler.trigger(this._element, EVENT_HIDDEN$4); 3049 }); 3050 } 3051 3052 _isAnimated() { 3053 return this._element.classList.contains(CLASS_NAME_FADE$3); 3054 } 3055 3056 _triggerBackdropTransition() { 3057 const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1); 3058 3059 if (hideEvent.defaultPrevented) { 3060 return; 3061 } 3062 3063 const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; 3064 const initialOverflowY = this._element.style.overflowY; // return if the following background transition hasn't yet completed 3065 3066 if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) { 3067 return; 3068 } 3069 3070 if (!isModalOverflowing) { 3071 this._element.style.overflowY = 'hidden'; 3072 } 3073 3074 this._element.classList.add(CLASS_NAME_STATIC); 3075 3076 this._queueCallback(() => { 3077 this._element.classList.remove(CLASS_NAME_STATIC); 3078 3079 this._queueCallback(() => { 3080 this._element.style.overflowY = initialOverflowY; 3081 }, this._dialog); 3082 }, this._dialog); 3083 3084 this._element.focus(); 3085 } 3086 /** 3087 * The following methods are used to handle overflowing modals 3088 */ 3089 3090 3091 _adjustDialog() { 3092 const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; 3093 3094 const scrollbarWidth = this._scrollBar.getWidth(); 3095 3096 const isBodyOverflowing = scrollbarWidth > 0; 3097 3098 if (isBodyOverflowing && !isModalOverflowing) { 3099 const property = isRTL() ? 'paddingLeft' : 'paddingRight'; 3100 this._element.style[property] = `${scrollbarWidth}px`; 3101 } 3102 3103 if (!isBodyOverflowing && isModalOverflowing) { 3104 const property = isRTL() ? 'paddingRight' : 'paddingLeft'; 3105 this._element.style[property] = `${scrollbarWidth}px`; 3106 } 3107 } 3108 3109 _resetAdjustments() { 3110 this._element.style.paddingLeft = ''; 3111 this._element.style.paddingRight = ''; 3112 } // Static 3113 3114 3115 static jQueryInterface(config, relatedTarget) { 3116 return this.each(function () { 3117 const data = Modal.getOrCreateInstance(this, config); 3118 3119 if (typeof config !== 'string') { 3120 return; 3121 } 3122 3123 if (typeof data[config] === 'undefined') { 3124 throw new TypeError(`No method named "${config}"`); 3125 } 3126 3127 data[config](relatedTarget); 3128 }); 3129 } 3130 3131 } 3132 /** 3133 * Data API implementation 3134 */ 3135 3136 3137 EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) { 3138 const target = getElementFromSelector(this); 3139 3140 if (['A', 'AREA'].includes(this.tagName)) { 3141 event.preventDefault(); 3142 } 3143 3144 EventHandler.one(target, EVENT_SHOW$4, showEvent => { 3145 if (showEvent.defaultPrevented) { 3146 // only register focus restorer if modal will actually get shown 3147 return; 3148 } 3149 3150 EventHandler.one(target, EVENT_HIDDEN$4, () => { 3151 if (isVisible(this)) { 3152 this.focus(); 3153 } 3154 }); 3155 }); // avoid conflict when clicking modal toggler while another one is open 3156 3157 const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1); 3158 3159 if (alreadyOpen) { 3160 Modal.getInstance(alreadyOpen).hide(); 3161 } 3162 3163 const data = Modal.getOrCreateInstance(target); 3164 data.toggle(this); 3165 }); 3166 enableDismissTrigger(Modal); 3167 /** 3168 * jQuery 3169 */ 3170 3171 defineJQueryPlugin(Modal); 3172 3173 /** 3174 * -------------------------------------------------------------------------- 3175 * Bootstrap (v5.2.1): offcanvas.js 3176 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 3177 * -------------------------------------------------------------------------- 3178 */ 3179 /** 3180 * Constants 3181 */ 3182 3183 const NAME$6 = 'offcanvas'; 3184 const DATA_KEY$3 = 'bs.offcanvas'; 3185 const EVENT_KEY$3 = `.${DATA_KEY$3}`; 3186 const DATA_API_KEY$1 = '.data-api'; 3187 const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`; 3188 const ESCAPE_KEY = 'Escape'; 3189 const CLASS_NAME_SHOW$3 = 'show'; 3190 const CLASS_NAME_SHOWING$1 = 'showing'; 3191 const CLASS_NAME_HIDING = 'hiding'; 3192 const CLASS_NAME_BACKDROP = 'offcanvas-backdrop'; 3193 const OPEN_SELECTOR = '.offcanvas.show'; 3194 const EVENT_SHOW$3 = `show${EVENT_KEY$3}`; 3195 const EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`; 3196 const EVENT_HIDE$3 = `hide${EVENT_KEY$3}`; 3197 const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`; 3198 const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`; 3199 const EVENT_RESIZE = `resize${EVENT_KEY$3}`; 3200 const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`; 3201 const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`; 3202 const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]'; 3203 const Default$5 = { 3204 backdrop: true, 3205 keyboard: true, 3206 scroll: false 3207 }; 3208 const DefaultType$5 = { 3209 backdrop: '(boolean|string)', 3210 keyboard: 'boolean', 3211 scroll: 'boolean' 3212 }; 3213 /** 3214 * Class definition 3215 */ 3216 3217 class Offcanvas extends BaseComponent { 3218 constructor(element, config) { 3219 super(element, config); 3220 this._isShown = false; 3221 this._backdrop = this._initializeBackDrop(); 3222 this._focustrap = this._initializeFocusTrap(); 3223 3224 this._addEventListeners(); 3225 } // Getters 3226 3227 3228 static get Default() { 3229 return Default$5; 3230 } 3231 3232 static get DefaultType() { 3233 return DefaultType$5; 3234 } 3235 3236 static get NAME() { 3237 return NAME$6; 3238 } // Public 3239 3240 3241 toggle(relatedTarget) { 3242 return this._isShown ? this.hide() : this.show(relatedTarget); 3243 } 3244 3245 show(relatedTarget) { 3246 if (this._isShown) { 3247 return; 3248 } 3249 3250 const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, { 3251 relatedTarget 3252 }); 3253 3254 if (showEvent.defaultPrevented) { 3255 return; 3256 } 3257 3258 this._isShown = true; 3259 3260 this._backdrop.show(); 3261 3262 if (!this._config.scroll) { 3263 new ScrollBarHelper().hide(); 3264 } 3265 3266 this._element.setAttribute('aria-modal', true); 3267 3268 this._element.setAttribute('role', 'dialog'); 3269 3270 this._element.classList.add(CLASS_NAME_SHOWING$1); 3271 3272 const completeCallBack = () => { 3273 if (!this._config.scroll || this._config.backdrop) { 3274 this._focustrap.activate(); 3275 } 3276 3277 this._element.classList.add(CLASS_NAME_SHOW$3); 3278 3279 this._element.classList.remove(CLASS_NAME_SHOWING$1); 3280 3281 EventHandler.trigger(this._element, EVENT_SHOWN$3, { 3282 relatedTarget 3283 }); 3284 }; 3285 3286 this._queueCallback(completeCallBack, this._element, true); 3287 } 3288 3289 hide() { 3290 if (!this._isShown) { 3291 return; 3292 } 3293 3294 const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3); 3295 3296 if (hideEvent.defaultPrevented) { 3297 return; 3298 } 3299 3300 this._focustrap.deactivate(); 3301 3302 this._element.blur(); 3303 3304 this._isShown = false; 3305 3306 this._element.classList.add(CLASS_NAME_HIDING); 3307 3308 this._backdrop.hide(); 3309 3310 const completeCallback = () => { 3311 this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING); 3312 3313 this._element.removeAttribute('aria-modal'); 3314 3315 this._element.removeAttribute('role'); 3316 3317 if (!this._config.scroll) { 3318 new ScrollBarHelper().reset(); 3319 } 3320 3321 EventHandler.trigger(this._element, EVENT_HIDDEN$3); 3322 }; 3323 3324 this._queueCallback(completeCallback, this._element, true); 3325 } 3326 3327 dispose() { 3328 this._backdrop.dispose(); 3329 3330 this._focustrap.deactivate(); 3331 3332 super.dispose(); 3333 } // Private 3334 3335 3336 _initializeBackDrop() { 3337 const clickCallback = () => { 3338 if (this._config.backdrop === 'static') { 3339 EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); 3340 return; 3341 } 3342 3343 this.hide(); 3344 }; // 'static' option will be translated to true, and booleans will keep their value 3345 3346 3347 const isVisible = Boolean(this._config.backdrop); 3348 return new Backdrop({ 3349 className: CLASS_NAME_BACKDROP, 3350 isVisible, 3351 isAnimated: true, 3352 rootElement: this._element.parentNode, 3353 clickCallback: isVisible ? clickCallback : null 3354 }); 3355 } 3356 3357 _initializeFocusTrap() { 3358 return new FocusTrap({ 3359 trapElement: this._element 3360 }); 3361 } 3362 3363 _addEventListeners() { 3364 EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { 3365 if (event.key !== ESCAPE_KEY) { 3366 return; 3367 } 3368 3369 if (!this._config.keyboard) { 3370 EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); 3371 return; 3372 } 3373 3374 this.hide(); 3375 }); 3376 } // Static 3377 3378 3379 static jQueryInterface(config) { 3380 return this.each(function () { 3381 const data = Offcanvas.getOrCreateInstance(this, config); 3382 3383 if (typeof config !== 'string') { 3384 return; 3385 } 3386 3387 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { 3388 throw new TypeError(`No method named "${config}"`); 3389 } 3390 3391 data[config](this); 3392 }); 3393 } 3394 3395 } 3396 /** 3397 * Data API implementation 3398 */ 3399 3400 3401 EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) { 3402 const target = getElementFromSelector(this); 3403 3404 if (['A', 'AREA'].includes(this.tagName)) { 3405 event.preventDefault(); 3406 } 3407 3408 if (isDisabled(this)) { 3409 return; 3410 } 3411 3412 EventHandler.one(target, EVENT_HIDDEN$3, () => { 3413 // focus on trigger when it is closed 3414 if (isVisible(this)) { 3415 this.focus(); 3416 } 3417 }); // avoid conflict when clicking a toggler of an offcanvas, while another is open 3418 3419 const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR); 3420 3421 if (alreadyOpen && alreadyOpen !== target) { 3422 Offcanvas.getInstance(alreadyOpen).hide(); 3423 } 3424 3425 const data = Offcanvas.getOrCreateInstance(target); 3426 data.toggle(this); 3427 }); 3428 EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => { 3429 for (const selector of SelectorEngine.find(OPEN_SELECTOR)) { 3430 Offcanvas.getOrCreateInstance(selector).show(); 3431 } 3432 }); 3433 EventHandler.on(window, EVENT_RESIZE, () => { 3434 for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) { 3435 if (getComputedStyle(element).position !== 'fixed') { 3436 Offcanvas.getOrCreateInstance(element).hide(); 3437 } 3438 } 3439 }); 3440 enableDismissTrigger(Offcanvas); 3441 /** 3442 * jQuery 3443 */ 3444 3445 defineJQueryPlugin(Offcanvas); 3446 3447 /** 3448 * -------------------------------------------------------------------------- 3449 * Bootstrap (v5.2.1): util/sanitizer.js 3450 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 3451 * -------------------------------------------------------------------------- 3452 */ 3453 const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); 3454 const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; 3455 /** 3456 * A pattern that recognizes a commonly useful subset of URLs that are safe. 3457 * 3458 * Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts 3459 */ 3460 3461 const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i; 3462 /** 3463 * A pattern that matches safe data URLs. Only matches image, video and audio types. 3464 * 3465 * Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts 3466 */ 3467 3468 const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; 3469 3470 const allowedAttribute = (attribute, allowedAttributeList) => { 3471 const attributeName = attribute.nodeName.toLowerCase(); 3472 3473 if (allowedAttributeList.includes(attributeName)) { 3474 if (uriAttributes.has(attributeName)) { 3475 return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)); 3476 } 3477 3478 return true; 3479 } // Check if a regular expression validates the attribute. 3480 3481 3482 return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName)); 3483 }; 3484 3485 const DefaultAllowlist = { 3486 // Global attributes allowed on any supplied element below. 3487 '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], 3488 a: ['target', 'href', 'title', 'rel'], 3489 area: [], 3490 b: [], 3491 br: [], 3492 col: [], 3493 code: [], 3494 div: [], 3495 em: [], 3496 hr: [], 3497 h1: [], 3498 h2: [], 3499 h3: [], 3500 h4: [], 3501 h5: [], 3502 h6: [], 3503 i: [], 3504 img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], 3505 li: [], 3506 ol: [], 3507 p: [], 3508 pre: [], 3509 s: [], 3510 small: [], 3511 span: [], 3512 sub: [], 3513 sup: [], 3514 strong: [], 3515 u: [], 3516 ul: [] 3517 }; 3518 function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) { 3519 if (!unsafeHtml.length) { 3520 return unsafeHtml; 3521 } 3522 3523 if (sanitizeFunction && typeof sanitizeFunction === 'function') { 3524 return sanitizeFunction(unsafeHtml); 3525 } 3526 3527 const domParser = new window.DOMParser(); 3528 const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); 3529 const elements = [].concat(...createdDocument.body.querySelectorAll('*')); 3530 3531 for (const element of elements) { 3532 const elementName = element.nodeName.toLowerCase(); 3533 3534 if (!Object.keys(allowList).includes(elementName)) { 3535 element.remove(); 3536 continue; 3537 } 3538 3539 const attributeList = [].concat(...element.attributes); 3540 const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []); 3541 3542 for (const attribute of attributeList) { 3543 if (!allowedAttribute(attribute, allowedAttributes)) { 3544 element.removeAttribute(attribute.nodeName); 3545 } 3546 } 3547 } 3548 3549 return createdDocument.body.innerHTML; 3550 } 3551 3552 /** 3553 * -------------------------------------------------------------------------- 3554 * Bootstrap (v5.2.1): util/template-factory.js 3555 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 3556 * -------------------------------------------------------------------------- 3557 */ 3558 /** 3559 * Constants 3560 */ 3561 3562 const NAME$5 = 'TemplateFactory'; 3563 const Default$4 = { 3564 allowList: DefaultAllowlist, 3565 content: {}, 3566 // { selector : text , selector2 : text2 , } 3567 extraClass: '', 3568 html: false, 3569 sanitize: true, 3570 sanitizeFn: null, 3571 template: '<div></div>' 3572 }; 3573 const DefaultType$4 = { 3574 allowList: 'object', 3575 content: 'object', 3576 extraClass: '(string|function)', 3577 html: 'boolean', 3578 sanitize: 'boolean', 3579 sanitizeFn: '(null|function)', 3580 template: 'string' 3581 }; 3582 const DefaultContentType = { 3583 entry: '(string|element|function|null)', 3584 selector: '(string|element)' 3585 }; 3586 /** 3587 * Class definition 3588 */ 3589 3590 class TemplateFactory extends Config { 3591 constructor(config) { 3592 super(); 3593 this._config = this._getConfig(config); 3594 } // Getters 3595 3596 3597 static get Default() { 3598 return Default$4; 3599 } 3600 3601 static get DefaultType() { 3602 return DefaultType$4; 3603 } 3604 3605 static get NAME() { 3606 return NAME$5; 3607 } // Public 3608 3609 3610 getContent() { 3611 return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean); 3612 } 3613 3614 hasContent() { 3615 return this.getContent().length > 0; 3616 } 3617 3618 changeContent(content) { 3619 this._checkContent(content); 3620 3621 this._config.content = { ...this._config.content, 3622 ...content 3623 }; 3624 return this; 3625 } 3626 3627 toHtml() { 3628 const templateWrapper = document.createElement('div'); 3629 templateWrapper.innerHTML = this._maybeSanitize(this._config.template); 3630 3631 for (const [selector, text] of Object.entries(this._config.content)) { 3632 this._setContent(templateWrapper, text, selector); 3633 } 3634 3635 const template = templateWrapper.children[0]; 3636 3637 const extraClass = this._resolvePossibleFunction(this._config.extraClass); 3638 3639 if (extraClass) { 3640 template.classList.add(...extraClass.split(' ')); 3641 } 3642 3643 return template; 3644 } // Private 3645 3646 3647 _typeCheckConfig(config) { 3648 super._typeCheckConfig(config); 3649 3650 this._checkContent(config.content); 3651 } 3652 3653 _checkContent(arg) { 3654 for (const [selector, content] of Object.entries(arg)) { 3655 super._typeCheckConfig({ 3656 selector, 3657 entry: content 3658 }, DefaultContentType); 3659 } 3660 } 3661 3662 _setContent(template, content, selector) { 3663 const templateElement = SelectorEngine.findOne(selector, template); 3664 3665 if (!templateElement) { 3666 return; 3667 } 3668 3669 content = this._resolvePossibleFunction(content); 3670 3671 if (!content) { 3672 templateElement.remove(); 3673 return; 3674 } 3675 3676 if (isElement(content)) { 3677 this._putElementInTemplate(getElement(content), templateElement); 3678 3679 return; 3680 } 3681 3682 if (this._config.html) { 3683 templateElement.innerHTML = this._maybeSanitize(content); 3684 return; 3685 } 3686 3687 templateElement.textContent = content; 3688 } 3689 3690 _maybeSanitize(arg) { 3691 return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg; 3692 } 3693 3694 _resolvePossibleFunction(arg) { 3695 return typeof arg === 'function' ? arg(this) : arg; 3696 } 3697 3698 _putElementInTemplate(element, templateElement) { 3699 if (this._config.html) { 3700 templateElement.innerHTML = ''; 3701 templateElement.append(element); 3702 return; 3703 } 3704 3705 templateElement.textContent = element.textContent; 3706 } 3707 3708 } 3709 3710 /** 3711 * -------------------------------------------------------------------------- 3712 * Bootstrap (v5.2.1): tooltip.js 3713 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 3714 * -------------------------------------------------------------------------- 3715 */ 3716 /** 3717 * Constants 3718 */ 3719 3720 const NAME$4 = 'tooltip'; 3721 const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); 3722 const CLASS_NAME_FADE$2 = 'fade'; 3723 const CLASS_NAME_MODAL = 'modal'; 3724 const CLASS_NAME_SHOW$2 = 'show'; 3725 const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; 3726 const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`; 3727 const EVENT_MODAL_HIDE = 'hide.bs.modal'; 3728 const TRIGGER_HOVER = 'hover'; 3729 const TRIGGER_FOCUS = 'focus'; 3730 const TRIGGER_CLICK = 'click'; 3731 const TRIGGER_MANUAL = 'manual'; 3732 const EVENT_HIDE$2 = 'hide'; 3733 const EVENT_HIDDEN$2 = 'hidden'; 3734 const EVENT_SHOW$2 = 'show'; 3735 const EVENT_SHOWN$2 = 'shown'; 3736 const EVENT_INSERTED = 'inserted'; 3737 const EVENT_CLICK$1 = 'click'; 3738 const EVENT_FOCUSIN$1 = 'focusin'; 3739 const EVENT_FOCUSOUT$1 = 'focusout'; 3740 const EVENT_MOUSEENTER = 'mouseenter'; 3741 const EVENT_MOUSELEAVE = 'mouseleave'; 3742 const AttachmentMap = { 3743 AUTO: 'auto', 3744 TOP: 'top', 3745 RIGHT: isRTL() ? 'left' : 'right', 3746 BOTTOM: 'bottom', 3747 LEFT: isRTL() ? 'right' : 'left' 3748 }; 3749 const Default$3 = { 3750 allowList: DefaultAllowlist, 3751 animation: true, 3752 boundary: 'clippingParents', 3753 container: false, 3754 customClass: '', 3755 delay: 0, 3756 fallbackPlacements: ['top', 'right', 'bottom', 'left'], 3757 html: false, 3758 offset: [0, 0], 3759 placement: 'top', 3760 popperConfig: null, 3761 sanitize: true, 3762 sanitizeFn: null, 3763 selector: false, 3764 template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>', 3765 title: '', 3766 trigger: 'hover focus' 3767 }; 3768 const DefaultType$3 = { 3769 allowList: 'object', 3770 animation: 'boolean', 3771 boundary: '(string|element)', 3772 container: '(string|element|boolean)', 3773 customClass: '(string|function)', 3774 delay: '(number|object)', 3775 fallbackPlacements: 'array', 3776 html: 'boolean', 3777 offset: '(array|string|function)', 3778 placement: '(string|function)', 3779 popperConfig: '(null|object|function)', 3780 sanitize: 'boolean', 3781 sanitizeFn: '(null|function)', 3782 selector: '(string|boolean)', 3783 template: 'string', 3784 title: '(string|element|function)', 3785 trigger: 'string' 3786 }; 3787 /** 3788 * Class definition 3789 */ 3790 3791 class Tooltip extends BaseComponent { 3792 constructor(element, config) { 3793 if (typeof Popper__namespace === 'undefined') { 3794 throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)'); 3795 } 3796 3797 super(element, config); // Private 3798 3799 this._isEnabled = true; 3800 this._timeout = 0; 3801 this._isHovered = null; 3802 this._activeTrigger = {}; 3803 this._popper = null; 3804 this._templateFactory = null; 3805 this._newContent = null; // Protected 3806 3807 this.tip = null; 3808 3809 this._setListeners(); 3810 } // Getters 3811 3812 3813 static get Default() { 3814 return Default$3; 3815 } 3816 3817 static get DefaultType() { 3818 return DefaultType$3; 3819 } 3820 3821 static get NAME() { 3822 return NAME$4; 3823 } // Public 3824 3825 3826 enable() { 3827 this._isEnabled = true; 3828 } 3829 3830 disable() { 3831 this._isEnabled = false; 3832 } 3833 3834 toggleEnabled() { 3835 this._isEnabled = !this._isEnabled; 3836 } 3837 3838 toggle(event) { 3839 if (!this._isEnabled) { 3840 return; 3841 } 3842 3843 if (event) { 3844 const context = this._initializeOnDelegatedTarget(event); 3845 3846 context._activeTrigger.click = !context._activeTrigger.click; 3847 3848 if (context._isWithActiveTrigger()) { 3849 context._enter(); 3850 } else { 3851 context._leave(); 3852 } 3853 3854 return; 3855 } 3856 3857 if (this._isShown()) { 3858 this._leave(); 3859 3860 return; 3861 } 3862 3863 this._enter(); 3864 } 3865 3866 dispose() { 3867 clearTimeout(this._timeout); 3868 EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); 3869 3870 if (this.tip) { 3871 this.tip.remove(); 3872 } 3873 3874 if (this._config.originalTitle) { 3875 this._element.setAttribute('title', this._config.originalTitle); 3876 } 3877 3878 this._disposePopper(); 3879 3880 super.dispose(); 3881 } 3882 3883 show() { 3884 if (this._element.style.display === 'none') { 3885 throw new Error('Please use show on visible elements'); 3886 } 3887 3888 if (!(this._isWithContent() && this._isEnabled)) { 3889 return; 3890 } 3891 3892 const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2)); 3893 const shadowRoot = findShadowRoot(this._element); 3894 3895 const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element); 3896 3897 if (showEvent.defaultPrevented || !isInTheDom) { 3898 return; 3899 } // todo v6 remove this OR make it optional 3900 3901 3902 if (this.tip) { 3903 this.tip.remove(); 3904 this.tip = null; 3905 } 3906 3907 const tip = this._getTipElement(); 3908 3909 this._element.setAttribute('aria-describedby', tip.getAttribute('id')); 3910 3911 const { 3912 container 3913 } = this._config; 3914 3915 if (!this._element.ownerDocument.documentElement.contains(this.tip)) { 3916 container.append(tip); 3917 EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED)); 3918 } 3919 3920 if (this._popper) { 3921 this._popper.update(); 3922 } else { 3923 this._popper = this._createPopper(tip); 3924 } 3925 3926 tip.classList.add(CLASS_NAME_SHOW$2); // If this is a touch-enabled device we add extra 3927 // empty mouseover listeners to the body's immediate children; 3928 // only needed because of broken event delegation on iOS 3929 // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html 3930 3931 if ('ontouchstart' in document.documentElement) { 3932 for (const element of [].concat(...document.body.children)) { 3933 EventHandler.on(element, 'mouseover', noop); 3934 } 3935 } 3936 3937 const complete = () => { 3938 EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2)); 3939 3940 if (this._isHovered === false) { 3941 this._leave(); 3942 } 3943 3944 this._isHovered = false; 3945 }; 3946 3947 this._queueCallback(complete, this.tip, this._isAnimated()); 3948 } 3949 3950 hide() { 3951 if (!this._isShown()) { 3952 return; 3953 } 3954 3955 const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2)); 3956 3957 if (hideEvent.defaultPrevented) { 3958 return; 3959 } 3960 3961 const tip = this._getTipElement(); 3962 3963 tip.classList.remove(CLASS_NAME_SHOW$2); // If this is a touch-enabled device we remove the extra 3964 // empty mouseover listeners we added for iOS support 3965 3966 if ('ontouchstart' in document.documentElement) { 3967 for (const element of [].concat(...document.body.children)) { 3968 EventHandler.off(element, 'mouseover', noop); 3969 } 3970 } 3971 3972 this._activeTrigger[TRIGGER_CLICK] = false; 3973 this._activeTrigger[TRIGGER_FOCUS] = false; 3974 this._activeTrigger[TRIGGER_HOVER] = false; 3975 this._isHovered = null; // it is a trick to support manual triggering 3976 3977 const complete = () => { 3978 if (this._isWithActiveTrigger()) { 3979 return; 3980 } 3981 3982 if (!this._isHovered) { 3983 tip.remove(); 3984 } 3985 3986 this._element.removeAttribute('aria-describedby'); 3987 3988 EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2)); 3989 3990 this._disposePopper(); 3991 }; 3992 3993 this._queueCallback(complete, this.tip, this._isAnimated()); 3994 } 3995 3996 update() { 3997 if (this._popper) { 3998 this._popper.update(); 3999 } 4000 } // Protected 4001 4002 4003 _isWithContent() { 4004 return Boolean(this._getTitle()); 4005 } 4006 4007 _getTipElement() { 4008 if (!this.tip) { 4009 this.tip = this._createTipElement(this._newContent || this._getContentForTemplate()); 4010 } 4011 4012 return this.tip; 4013 } 4014 4015 _createTipElement(content) { 4016 const tip = this._getTemplateFactory(content).toHtml(); // todo: remove this check on v6 4017 4018 4019 if (!tip) { 4020 return null; 4021 } 4022 4023 tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2); // todo: on v6 the following can be achieved with CSS only 4024 4025 tip.classList.add(`bs-${this.constructor.NAME}-auto`); 4026 const tipId = getUID(this.constructor.NAME).toString(); 4027 tip.setAttribute('id', tipId); 4028 4029 if (this._isAnimated()) { 4030 tip.classList.add(CLASS_NAME_FADE$2); 4031 } 4032 4033 return tip; 4034 } 4035 4036 setContent(content) { 4037 this._newContent = content; 4038 4039 if (this._isShown()) { 4040 this._disposePopper(); 4041 4042 this.show(); 4043 } 4044 } 4045 4046 _getTemplateFactory(content) { 4047 if (this._templateFactory) { 4048 this._templateFactory.changeContent(content); 4049 } else { 4050 this._templateFactory = new TemplateFactory({ ...this._config, 4051 // the `content` var has to be after `this._config` 4052 // to override config.content in case of popover 4053 content, 4054 extraClass: this._resolvePossibleFunction(this._config.customClass) 4055 }); 4056 } 4057 4058 return this._templateFactory; 4059 } 4060 4061 _getContentForTemplate() { 4062 return { 4063 [SELECTOR_TOOLTIP_INNER]: this._getTitle() 4064 }; 4065 } 4066 4067 _getTitle() { 4068 return this._resolvePossibleFunction(this._config.title) || this._config.originalTitle; 4069 } // Private 4070 4071 4072 _initializeOnDelegatedTarget(event) { 4073 return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()); 4074 } 4075 4076 _isAnimated() { 4077 return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2); 4078 } 4079 4080 _isShown() { 4081 return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2); 4082 } 4083 4084 _createPopper(tip) { 4085 const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement; 4086 const attachment = AttachmentMap[placement.toUpperCase()]; 4087 return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment)); 4088 } 4089 4090 _getOffset() { 4091 const { 4092 offset 4093 } = this._config; 4094 4095 if (typeof offset === 'string') { 4096 return offset.split(',').map(value => Number.parseInt(value, 10)); 4097 } 4098 4099 if (typeof offset === 'function') { 4100 return popperData => offset(popperData, this._element); 4101 } 4102 4103 return offset; 4104 } 4105 4106 _resolvePossibleFunction(arg) { 4107 return typeof arg === 'function' ? arg.call(this._element) : arg; 4108 } 4109 4110 _getPopperConfig(attachment) { 4111 const defaultBsPopperConfig = { 4112 placement: attachment, 4113 modifiers: [{ 4114 name: 'flip', 4115 options: { 4116 fallbackPlacements: this._config.fallbackPlacements 4117 } 4118 }, { 4119 name: 'offset', 4120 options: { 4121 offset: this._getOffset() 4122 } 4123 }, { 4124 name: 'preventOverflow', 4125 options: { 4126 boundary: this._config.boundary 4127 } 4128 }, { 4129 name: 'arrow', 4130 options: { 4131 element: `.${this.constructor.NAME}-arrow` 4132 } 4133 }, { 4134 name: 'preSetPlacement', 4135 enabled: true, 4136 phase: 'beforeMain', 4137 fn: data => { 4138 // Pre-set Popper's placement attribute in order to read the arrow sizes properly. 4139 // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement 4140 this._getTipElement().setAttribute('data-popper-placement', data.state.placement); 4141 } 4142 }] 4143 }; 4144 return { ...defaultBsPopperConfig, 4145 ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) 4146 }; 4147 } 4148 4149 _setListeners() { 4150 const triggers = this._config.trigger.split(' '); 4151 4152 for (const trigger of triggers) { 4153 if (trigger === 'click') { 4154 EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => this.toggle(event)); 4155 } else if (trigger !== TRIGGER_MANUAL) { 4156 const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1); 4157 const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1); 4158 EventHandler.on(this._element, eventIn, this._config.selector, event => { 4159 const context = this._initializeOnDelegatedTarget(event); 4160 4161 context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; 4162 4163 context._enter(); 4164 }); 4165 EventHandler.on(this._element, eventOut, this._config.selector, event => { 4166 const context = this._initializeOnDelegatedTarget(event); 4167 4168 context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget); 4169 4170 context._leave(); 4171 }); 4172 } 4173 } 4174 4175 this._hideModalHandler = () => { 4176 if (this._element) { 4177 this.hide(); 4178 } 4179 }; 4180 4181 EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); 4182 4183 if (this._config.selector) { 4184 this._config = { ...this._config, 4185 trigger: 'manual', 4186 selector: '' 4187 }; 4188 } else { 4189 this._fixTitle(); 4190 } 4191 } 4192 4193 _fixTitle() { 4194 const title = this._config.originalTitle; 4195 4196 if (!title) { 4197 return; 4198 } 4199 4200 if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) { 4201 this._element.setAttribute('aria-label', title); 4202 } 4203 4204 this._element.removeAttribute('title'); 4205 } 4206 4207 _enter() { 4208 if (this._isShown() || this._isHovered) { 4209 this._isHovered = true; 4210 return; 4211 } 4212 4213 this._isHovered = true; 4214 4215 this._setTimeout(() => { 4216 if (this._isHovered) { 4217 this.show(); 4218 } 4219 }, this._config.delay.show); 4220 } 4221 4222 _leave() { 4223 if (this._isWithActiveTrigger()) { 4224 return; 4225 } 4226 4227 this._isHovered = false; 4228 4229 this._setTimeout(() => { 4230 if (!this._isHovered) { 4231 this.hide(); 4232 } 4233 }, this._config.delay.hide); 4234 } 4235 4236 _setTimeout(handler, timeout) { 4237 clearTimeout(this._timeout); 4238 this._timeout = setTimeout(handler, timeout); 4239 } 4240 4241 _isWithActiveTrigger() { 4242 return Object.values(this._activeTrigger).includes(true); 4243 } 4244 4245 _getConfig(config) { 4246 const dataAttributes = Manipulator.getDataAttributes(this._element); 4247 4248 for (const dataAttribute of Object.keys(dataAttributes)) { 4249 if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) { 4250 delete dataAttributes[dataAttribute]; 4251 } 4252 } 4253 4254 config = { ...dataAttributes, 4255 ...(typeof config === 'object' && config ? config : {}) 4256 }; 4257 config = this._mergeConfigObj(config); 4258 config = this._configAfterMerge(config); 4259 4260 this._typeCheckConfig(config); 4261 4262 return config; 4263 } 4264 4265 _configAfterMerge(config) { 4266 config.container = config.container === false ? document.body : getElement(config.container); 4267 4268 if (typeof config.delay === 'number') { 4269 config.delay = { 4270 show: config.delay, 4271 hide: config.delay 4272 }; 4273 } 4274 4275 config.originalTitle = this._element.getAttribute('title') || ''; 4276 4277 if (typeof config.title === 'number') { 4278 config.title = config.title.toString(); 4279 } 4280 4281 if (typeof config.content === 'number') { 4282 config.content = config.content.toString(); 4283 } 4284 4285 return config; 4286 } 4287 4288 _getDelegateConfig() { 4289 const config = {}; 4290 4291 for (const key in this._config) { 4292 if (this.constructor.Default[key] !== this._config[key]) { 4293 config[key] = this._config[key]; 4294 } 4295 } // In the future can be replaced with: 4296 // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]]) 4297 // `Object.fromEntries(keysWithDifferentValues)` 4298 4299 4300 return config; 4301 } 4302 4303 _disposePopper() { 4304 if (this._popper) { 4305 this._popper.destroy(); 4306 4307 this._popper = null; 4308 } 4309 } // Static 4310 4311 4312 static jQueryInterface(config) { 4313 return this.each(function () { 4314 const data = Tooltip.getOrCreateInstance(this, config); 4315 4316 if (typeof config !== 'string') { 4317 return; 4318 } 4319 4320 if (typeof data[config] === 'undefined') { 4321 throw new TypeError(`No method named "${config}"`); 4322 } 4323 4324 data[config](); 4325 }); 4326 } 4327 4328 } 4329 /** 4330 * jQuery 4331 */ 4332 4333 4334 defineJQueryPlugin(Tooltip); 4335 4336 /** 4337 * -------------------------------------------------------------------------- 4338 * Bootstrap (v5.2.1): popover.js 4339 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 4340 * -------------------------------------------------------------------------- 4341 */ 4342 /** 4343 * Constants 4344 */ 4345 4346 const NAME$3 = 'popover'; 4347 const SELECTOR_TITLE = '.popover-header'; 4348 const SELECTOR_CONTENT = '.popover-body'; 4349 const Default$2 = { ...Tooltip.Default, 4350 content: '', 4351 offset: [0, 8], 4352 placement: 'right', 4353 template: '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div>' + '</div>', 4354 trigger: 'click' 4355 }; 4356 const DefaultType$2 = { ...Tooltip.DefaultType, 4357 content: '(null|string|element|function)' 4358 }; 4359 /** 4360 * Class definition 4361 */ 4362 4363 class Popover extends Tooltip { 4364 // Getters 4365 static get Default() { 4366 return Default$2; 4367 } 4368 4369 static get DefaultType() { 4370 return DefaultType$2; 4371 } 4372 4373 static get NAME() { 4374 return NAME$3; 4375 } // Overrides 4376 4377 4378 _isWithContent() { 4379 return this._getTitle() || this._getContent(); 4380 } // Private 4381 4382 4383 _getContentForTemplate() { 4384 return { 4385 [SELECTOR_TITLE]: this._getTitle(), 4386 [SELECTOR_CONTENT]: this._getContent() 4387 }; 4388 } 4389 4390 _getContent() { 4391 return this._resolvePossibleFunction(this._config.content); 4392 } // Static 4393 4394 4395 static jQueryInterface(config) { 4396 return this.each(function () { 4397 const data = Popover.getOrCreateInstance(this, config); 4398 4399 if (typeof config !== 'string') { 4400 return; 4401 } 4402 4403 if (typeof data[config] === 'undefined') { 4404 throw new TypeError(`No method named "${config}"`); 4405 } 4406 4407 data[config](); 4408 }); 4409 } 4410 4411 } 4412 /** 4413 * jQuery 4414 */ 4415 4416 4417 defineJQueryPlugin(Popover); 4418 4419 /** 4420 * -------------------------------------------------------------------------- 4421 * Bootstrap (v5.2.1): scrollspy.js 4422 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 4423 * -------------------------------------------------------------------------- 4424 */ 4425 /** 4426 * Constants 4427 */ 4428 4429 const NAME$2 = 'scrollspy'; 4430 const DATA_KEY$2 = 'bs.scrollspy'; 4431 const EVENT_KEY$2 = `.${DATA_KEY$2}`; 4432 const DATA_API_KEY = '.data-api'; 4433 const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`; 4434 const EVENT_CLICK = `click${EVENT_KEY$2}`; 4435 const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`; 4436 const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; 4437 const CLASS_NAME_ACTIVE$1 = 'active'; 4438 const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'; 4439 const SELECTOR_TARGET_LINKS = '[href]'; 4440 const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'; 4441 const SELECTOR_NAV_LINKS = '.nav-link'; 4442 const SELECTOR_NAV_ITEMS = '.nav-item'; 4443 const SELECTOR_LIST_ITEMS = '.list-group-item'; 4444 const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`; 4445 const SELECTOR_DROPDOWN = '.dropdown'; 4446 const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle'; 4447 const Default$1 = { 4448 offset: null, 4449 // TODO: v6 @deprecated, keep it for backwards compatibility reasons 4450 rootMargin: '0px 0px -25%', 4451 smoothScroll: false, 4452 target: null, 4453 threshold: [0.1, 0.5, 1] 4454 }; 4455 const DefaultType$1 = { 4456 offset: '(number|null)', 4457 // TODO v6 @deprecated, keep it for backwards compatibility reasons 4458 rootMargin: 'string', 4459 smoothScroll: 'boolean', 4460 target: 'element', 4461 threshold: 'array' 4462 }; 4463 /** 4464 * Class definition 4465 */ 4466 4467 class ScrollSpy extends BaseComponent { 4468 constructor(element, config) { 4469 super(element, config); // this._element is the observablesContainer and config.target the menu links wrapper 4470 4471 this._targetLinks = new Map(); 4472 this._observableSections = new Map(); 4473 this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element; 4474 this._activeTarget = null; 4475 this._observer = null; 4476 this._previousScrollData = { 4477 visibleEntryTop: 0, 4478 parentScrollTop: 0 4479 }; 4480 this.refresh(); // initialize 4481 } // Getters 4482 4483 4484 static get Default() { 4485 return Default$1; 4486 } 4487 4488 static get DefaultType() { 4489 return DefaultType$1; 4490 } 4491 4492 static get NAME() { 4493 return NAME$2; 4494 } // Public 4495 4496 4497 refresh() { 4498 this._initializeTargetsAndObservables(); 4499 4500 this._maybeEnableSmoothScroll(); 4501 4502 if (this._observer) { 4503 this._observer.disconnect(); 4504 } else { 4505 this._observer = this._getNewObserver(); 4506 } 4507 4508 for (const section of this._observableSections.values()) { 4509 this._observer.observe(section); 4510 } 4511 } 4512 4513 dispose() { 4514 this._observer.disconnect(); 4515 4516 super.dispose(); 4517 } // Private 4518 4519 4520 _configAfterMerge(config) { 4521 // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case 4522 config.target = getElement(config.target) || document.body; // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only 4523 4524 config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin; 4525 4526 if (typeof config.threshold === 'string') { 4527 config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value)); 4528 } 4529 4530 return config; 4531 } 4532 4533 _maybeEnableSmoothScroll() { 4534 if (!this._config.smoothScroll) { 4535 return; 4536 } // unregister any previous listeners 4537 4538 4539 EventHandler.off(this._config.target, EVENT_CLICK); 4540 EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => { 4541 const observableSection = this._observableSections.get(event.target.hash); 4542 4543 if (observableSection) { 4544 event.preventDefault(); 4545 const root = this._rootElement || window; 4546 const height = observableSection.offsetTop - this._element.offsetTop; 4547 4548 if (root.scrollTo) { 4549 root.scrollTo({ 4550 top: height, 4551 behavior: 'smooth' 4552 }); 4553 return; 4554 } // Chrome 60 doesn't support `scrollTo` 4555 4556 4557 root.scrollTop = height; 4558 } 4559 }); 4560 } 4561 4562 _getNewObserver() { 4563 const options = { 4564 root: this._rootElement, 4565 threshold: this._config.threshold, 4566 rootMargin: this._config.rootMargin 4567 }; 4568 return new IntersectionObserver(entries => this._observerCallback(entries), options); 4569 } // The logic of selection 4570 4571 4572 _observerCallback(entries) { 4573 const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`); 4574 4575 const activate = entry => { 4576 this._previousScrollData.visibleEntryTop = entry.target.offsetTop; 4577 4578 this._process(targetElement(entry)); 4579 }; 4580 4581 const parentScrollTop = (this._rootElement || document.documentElement).scrollTop; 4582 const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop; 4583 this._previousScrollData.parentScrollTop = parentScrollTop; 4584 4585 for (const entry of entries) { 4586 if (!entry.isIntersecting) { 4587 this._activeTarget = null; 4588 4589 this._clearActiveClass(targetElement(entry)); 4590 4591 continue; 4592 } 4593 4594 const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop; // if we are scrolling down, pick the bigger offsetTop 4595 4596 if (userScrollsDown && entryIsLowerThanPrevious) { 4597 activate(entry); // if parent isn't scrolled, let's keep the first visible item, breaking the iteration 4598 4599 if (!parentScrollTop) { 4600 return; 4601 } 4602 4603 continue; 4604 } // if we are scrolling up, pick the smallest offsetTop 4605 4606 4607 if (!userScrollsDown && !entryIsLowerThanPrevious) { 4608 activate(entry); 4609 } 4610 } 4611 } 4612 4613 _initializeTargetsAndObservables() { 4614 this._targetLinks = new Map(); 4615 this._observableSections = new Map(); 4616 const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target); 4617 4618 for (const anchor of targetLinks) { 4619 // ensure that the anchor has an id and is not disabled 4620 if (!anchor.hash || isDisabled(anchor)) { 4621 continue; 4622 } 4623 4624 const observableSection = SelectorEngine.findOne(anchor.hash, this._element); // ensure that the observableSection exists & is visible 4625 4626 if (isVisible(observableSection)) { 4627 this._targetLinks.set(anchor.hash, anchor); 4628 4629 this._observableSections.set(anchor.hash, observableSection); 4630 } 4631 } 4632 } 4633 4634 _process(target) { 4635 if (this._activeTarget === target) { 4636 return; 4637 } 4638 4639 this._clearActiveClass(this._config.target); 4640 4641 this._activeTarget = target; 4642 target.classList.add(CLASS_NAME_ACTIVE$1); 4643 4644 this._activateParents(target); 4645 4646 EventHandler.trigger(this._element, EVENT_ACTIVATE, { 4647 relatedTarget: target 4648 }); 4649 } 4650 4651 _activateParents(target) { 4652 // Activate dropdown parents 4653 if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { 4654 SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1); 4655 return; 4656 } 4657 4658 for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) { 4659 // Set triggered links parents as active 4660 // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor 4661 for (const item of SelectorEngine.prev(listGroup, SELECTOR_LINK_ITEMS)) { 4662 item.classList.add(CLASS_NAME_ACTIVE$1); 4663 } 4664 } 4665 } 4666 4667 _clearActiveClass(parent) { 4668 parent.classList.remove(CLASS_NAME_ACTIVE$1); 4669 const activeNodes = SelectorEngine.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE$1}`, parent); 4670 4671 for (const node of activeNodes) { 4672 node.classList.remove(CLASS_NAME_ACTIVE$1); 4673 } 4674 } // Static 4675 4676 4677 static jQueryInterface(config) { 4678 return this.each(function () { 4679 const data = ScrollSpy.getOrCreateInstance(this, config); 4680 4681 if (typeof config !== 'string') { 4682 return; 4683 } 4684 4685 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { 4686 throw new TypeError(`No method named "${config}"`); 4687 } 4688 4689 data[config](); 4690 }); 4691 } 4692 4693 } 4694 /** 4695 * Data API implementation 4696 */ 4697 4698 4699 EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => { 4700 for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) { 4701 ScrollSpy.getOrCreateInstance(spy); 4702 } 4703 }); 4704 /** 4705 * jQuery 4706 */ 4707 4708 defineJQueryPlugin(ScrollSpy); 4709 4710 /** 4711 * -------------------------------------------------------------------------- 4712 * Bootstrap (v5.2.1): tab.js 4713 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 4714 * -------------------------------------------------------------------------- 4715 */ 4716 /** 4717 * Constants 4718 */ 4719 4720 const NAME$1 = 'tab'; 4721 const DATA_KEY$1 = 'bs.tab'; 4722 const EVENT_KEY$1 = `.${DATA_KEY$1}`; 4723 const EVENT_HIDE$1 = `hide${EVENT_KEY$1}`; 4724 const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$1}`; 4725 const EVENT_SHOW$1 = `show${EVENT_KEY$1}`; 4726 const EVENT_SHOWN$1 = `shown${EVENT_KEY$1}`; 4727 const EVENT_CLICK_DATA_API = `click${EVENT_KEY$1}`; 4728 const EVENT_KEYDOWN = `keydown${EVENT_KEY$1}`; 4729 const EVENT_LOAD_DATA_API = `load${EVENT_KEY$1}`; 4730 const ARROW_LEFT_KEY = 'ArrowLeft'; 4731 const ARROW_RIGHT_KEY = 'ArrowRight'; 4732 const ARROW_UP_KEY = 'ArrowUp'; 4733 const ARROW_DOWN_KEY = 'ArrowDown'; 4734 const CLASS_NAME_ACTIVE = 'active'; 4735 const CLASS_NAME_FADE$1 = 'fade'; 4736 const CLASS_NAME_SHOW$1 = 'show'; 4737 const CLASS_DROPDOWN = 'dropdown'; 4738 const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'; 4739 const SELECTOR_DROPDOWN_MENU = '.dropdown-menu'; 4740 const SELECTOR_DROPDOWN_ITEM = '.dropdown-item'; 4741 const NOT_SELECTOR_DROPDOWN_TOGGLE = ':not(.dropdown-toggle)'; 4742 const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]'; 4743 const SELECTOR_OUTER = '.nav-item, .list-group-item'; 4744 const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`; 4745 const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'; // todo:v6: could be only `tab` 4746 4747 const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`; 4748 const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`; 4749 /** 4750 * Class definition 4751 */ 4752 4753 class Tab extends BaseComponent { 4754 constructor(element) { 4755 super(element); 4756 this._parent = this._element.closest(SELECTOR_TAB_PANEL); 4757 4758 if (!this._parent) { 4759 return; // todo: should Throw exception on v6 4760 // throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`) 4761 } // Set up initial aria attributes 4762 4763 4764 this._setInitialAttributes(this._parent, this._getChildren()); 4765 4766 EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event)); 4767 } // Getters 4768 4769 4770 static get NAME() { 4771 return NAME$1; 4772 } // Public 4773 4774 4775 show() { 4776 // Shows this elem and deactivate the active sibling if exists 4777 const innerElem = this._element; 4778 4779 if (this._elemIsActive(innerElem)) { 4780 return; 4781 } // Search for active tab on same parent to deactivate it 4782 4783 4784 const active = this._getActiveElem(); 4785 4786 const hideEvent = active ? EventHandler.trigger(active, EVENT_HIDE$1, { 4787 relatedTarget: innerElem 4788 }) : null; 4789 const showEvent = EventHandler.trigger(innerElem, EVENT_SHOW$1, { 4790 relatedTarget: active 4791 }); 4792 4793 if (showEvent.defaultPrevented || hideEvent && hideEvent.defaultPrevented) { 4794 return; 4795 } 4796 4797 this._deactivate(active, innerElem); 4798 4799 this._activate(innerElem, active); 4800 } // Private 4801 4802 4803 _activate(element, relatedElem) { 4804 if (!element) { 4805 return; 4806 } 4807 4808 element.classList.add(CLASS_NAME_ACTIVE); 4809 4810 this._activate(getElementFromSelector(element)); // Search and activate/show the proper section 4811 4812 4813 const complete = () => { 4814 if (element.getAttribute('role') !== 'tab') { 4815 element.classList.add(CLASS_NAME_SHOW$1); 4816 return; 4817 } 4818 4819 element.focus(); 4820 element.removeAttribute('tabindex'); 4821 element.setAttribute('aria-selected', true); 4822 4823 this._toggleDropDown(element, true); 4824 4825 EventHandler.trigger(element, EVENT_SHOWN$1, { 4826 relatedTarget: relatedElem 4827 }); 4828 }; 4829 4830 this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1)); 4831 } 4832 4833 _deactivate(element, relatedElem) { 4834 if (!element) { 4835 return; 4836 } 4837 4838 element.classList.remove(CLASS_NAME_ACTIVE); 4839 element.blur(); 4840 4841 this._deactivate(getElementFromSelector(element)); // Search and deactivate the shown section too 4842 4843 4844 const complete = () => { 4845 if (element.getAttribute('role') !== 'tab') { 4846 element.classList.remove(CLASS_NAME_SHOW$1); 4847 return; 4848 } 4849 4850 element.setAttribute('aria-selected', false); 4851 element.setAttribute('tabindex', '-1'); 4852 4853 this._toggleDropDown(element, false); 4854 4855 EventHandler.trigger(element, EVENT_HIDDEN$1, { 4856 relatedTarget: relatedElem 4857 }); 4858 }; 4859 4860 this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1)); 4861 } 4862 4863 _keydown(event) { 4864 if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY].includes(event.key)) { 4865 return; 4866 } 4867 4868 event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page 4869 4870 event.preventDefault(); 4871 const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key); 4872 const nextActiveElement = getNextActiveElement(this._getChildren().filter(element => !isDisabled(element)), event.target, isNext, true); 4873 4874 if (nextActiveElement) { 4875 Tab.getOrCreateInstance(nextActiveElement).show(); 4876 } 4877 } 4878 4879 _getChildren() { 4880 // collection of inner elements 4881 return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent); 4882 } 4883 4884 _getActiveElem() { 4885 return this._getChildren().find(child => this._elemIsActive(child)) || null; 4886 } 4887 4888 _setInitialAttributes(parent, children) { 4889 this._setAttributeIfNotExists(parent, 'role', 'tablist'); 4890 4891 for (const child of children) { 4892 this._setInitialAttributesOnChild(child); 4893 } 4894 } 4895 4896 _setInitialAttributesOnChild(child) { 4897 child = this._getInnerElement(child); 4898 4899 const isActive = this._elemIsActive(child); 4900 4901 const outerElem = this._getOuterElement(child); 4902 4903 child.setAttribute('aria-selected', isActive); 4904 4905 if (outerElem !== child) { 4906 this._setAttributeIfNotExists(outerElem, 'role', 'presentation'); 4907 } 4908 4909 if (!isActive) { 4910 child.setAttribute('tabindex', '-1'); 4911 } 4912 4913 this._setAttributeIfNotExists(child, 'role', 'tab'); // set attributes to the related panel too 4914 4915 4916 this._setInitialAttributesOnTargetPanel(child); 4917 } 4918 4919 _setInitialAttributesOnTargetPanel(child) { 4920 const target = getElementFromSelector(child); 4921 4922 if (!target) { 4923 return; 4924 } 4925 4926 this._setAttributeIfNotExists(target, 'role', 'tabpanel'); 4927 4928 if (child.id) { 4929 this._setAttributeIfNotExists(target, 'aria-labelledby', `#${child.id}`); 4930 } 4931 } 4932 4933 _toggleDropDown(element, open) { 4934 const outerElem = this._getOuterElement(element); 4935 4936 if (!outerElem.classList.contains(CLASS_DROPDOWN)) { 4937 return; 4938 } 4939 4940 const toggle = (selector, className) => { 4941 const element = SelectorEngine.findOne(selector, outerElem); 4942 4943 if (element) { 4944 element.classList.toggle(className, open); 4945 } 4946 }; 4947 4948 toggle(SELECTOR_DROPDOWN_TOGGLE, CLASS_NAME_ACTIVE); 4949 toggle(SELECTOR_DROPDOWN_MENU, CLASS_NAME_SHOW$1); 4950 toggle(SELECTOR_DROPDOWN_ITEM, CLASS_NAME_ACTIVE); 4951 outerElem.setAttribute('aria-expanded', open); 4952 } 4953 4954 _setAttributeIfNotExists(element, attribute, value) { 4955 if (!element.hasAttribute(attribute)) { 4956 element.setAttribute(attribute, value); 4957 } 4958 } 4959 4960 _elemIsActive(elem) { 4961 return elem.classList.contains(CLASS_NAME_ACTIVE); 4962 } // Try to get the inner element (usually the .nav-link) 4963 4964 4965 _getInnerElement(elem) { 4966 return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem); 4967 } // Try to get the outer element (usually the .nav-item) 4968 4969 4970 _getOuterElement(elem) { 4971 return elem.closest(SELECTOR_OUTER) || elem; 4972 } // Static 4973 4974 4975 static jQueryInterface(config) { 4976 return this.each(function () { 4977 const data = Tab.getOrCreateInstance(this); 4978 4979 if (typeof config !== 'string') { 4980 return; 4981 } 4982 4983 if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { 4984 throw new TypeError(`No method named "${config}"`); 4985 } 4986 4987 data[config](); 4988 }); 4989 } 4990 4991 } 4992 /** 4993 * Data API implementation 4994 */ 4995 4996 4997 EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { 4998 if (['A', 'AREA'].includes(this.tagName)) { 4999 event.preventDefault(); 5000 } 5001 5002 if (isDisabled(this)) { 5003 return; 5004 } 5005 5006 Tab.getOrCreateInstance(this).show(); 5007 }); 5008 /** 5009 * Initialize on focus 5010 */ 5011 5012 EventHandler.on(window, EVENT_LOAD_DATA_API, () => { 5013 for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE_ACTIVE)) { 5014 Tab.getOrCreateInstance(element); 5015 } 5016 }); 5017 /** 5018 * jQuery 5019 */ 5020 5021 defineJQueryPlugin(Tab); 5022 5023 /** 5024 * -------------------------------------------------------------------------- 5025 * Bootstrap (v5.2.1): toast.js 5026 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 5027 * -------------------------------------------------------------------------- 5028 */ 5029 /** 5030 * Constants 5031 */ 5032 5033 const NAME = 'toast'; 5034 const DATA_KEY = 'bs.toast'; 5035 const EVENT_KEY = `.${DATA_KEY}`; 5036 const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`; 5037 const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`; 5038 const EVENT_FOCUSIN = `focusin${EVENT_KEY}`; 5039 const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`; 5040 const EVENT_HIDE = `hide${EVENT_KEY}`; 5041 const EVENT_HIDDEN = `hidden${EVENT_KEY}`; 5042 const EVENT_SHOW = `show${EVENT_KEY}`; 5043 const EVENT_SHOWN = `shown${EVENT_KEY}`; 5044 const CLASS_NAME_FADE = 'fade'; 5045 const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility 5046 5047 const CLASS_NAME_SHOW = 'show'; 5048 const CLASS_NAME_SHOWING = 'showing'; 5049 const DefaultType = { 5050 animation: 'boolean', 5051 autohide: 'boolean', 5052 delay: 'number' 5053 }; 5054 const Default = { 5055 animation: true, 5056 autohide: true, 5057 delay: 5000 5058 }; 5059 /** 5060 * Class definition 5061 */ 5062 5063 class Toast extends BaseComponent { 5064 constructor(element, config) { 5065 super(element, config); 5066 this._timeout = null; 5067 this._hasMouseInteraction = false; 5068 this._hasKeyboardInteraction = false; 5069 5070 this._setListeners(); 5071 } // Getters 5072 5073 5074 static get Default() { 5075 return Default; 5076 } 5077 5078 static get DefaultType() { 5079 return DefaultType; 5080 } 5081 5082 static get NAME() { 5083 return NAME; 5084 } // Public 5085 5086 5087 show() { 5088 const showEvent = EventHandler.trigger(this._element, EVENT_SHOW); 5089 5090 if (showEvent.defaultPrevented) { 5091 return; 5092 } 5093 5094 this._clearTimeout(); 5095 5096 if (this._config.animation) { 5097 this._element.classList.add(CLASS_NAME_FADE); 5098 } 5099 5100 const complete = () => { 5101 this._element.classList.remove(CLASS_NAME_SHOWING); 5102 5103 EventHandler.trigger(this._element, EVENT_SHOWN); 5104 5105 this._maybeScheduleHide(); 5106 }; 5107 5108 this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated 5109 5110 5111 reflow(this._element); 5112 5113 this._element.classList.add(CLASS_NAME_SHOW, CLASS_NAME_SHOWING); 5114 5115 this._queueCallback(complete, this._element, this._config.animation); 5116 } 5117 5118 hide() { 5119 if (!this.isShown()) { 5120 return; 5121 } 5122 5123 const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE); 5124 5125 if (hideEvent.defaultPrevented) { 5126 return; 5127 } 5128 5129 const complete = () => { 5130 this._element.classList.add(CLASS_NAME_HIDE); // @deprecated 5131 5132 5133 this._element.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW); 5134 5135 EventHandler.trigger(this._element, EVENT_HIDDEN); 5136 }; 5137 5138 this._element.classList.add(CLASS_NAME_SHOWING); 5139 5140 this._queueCallback(complete, this._element, this._config.animation); 5141 } 5142 5143 dispose() { 5144 this._clearTimeout(); 5145 5146 if (this.isShown()) { 5147 this._element.classList.remove(CLASS_NAME_SHOW); 5148 } 5149 5150 super.dispose(); 5151 } 5152 5153 isShown() { 5154 return this._element.classList.contains(CLASS_NAME_SHOW); 5155 } // Private 5156 5157 5158 _maybeScheduleHide() { 5159 if (!this._config.autohide) { 5160 return; 5161 } 5162 5163 if (this._hasMouseInteraction || this._hasKeyboardInteraction) { 5164 return; 5165 } 5166 5167 this._timeout = setTimeout(() => { 5168 this.hide(); 5169 }, this._config.delay); 5170 } 5171 5172 _onInteraction(event, isInteracting) { 5173 switch (event.type) { 5174 case 'mouseover': 5175 case 'mouseout': 5176 this._hasMouseInteraction = isInteracting; 5177 break; 5178 5179 case 'focusin': 5180 case 'focusout': 5181 this._hasKeyboardInteraction = isInteracting; 5182 break; 5183 } 5184 5185 if (isInteracting) { 5186 this._clearTimeout(); 5187 5188 return; 5189 } 5190 5191 const nextElement = event.relatedTarget; 5192 5193 if (this._element === nextElement || this._element.contains(nextElement)) { 5194 return; 5195 } 5196 5197 this._maybeScheduleHide(); 5198 } 5199 5200 _setListeners() { 5201 EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true)); 5202 EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false)); 5203 EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true)); 5204 EventHandler.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false)); 5205 } 5206 5207 _clearTimeout() { 5208 clearTimeout(this._timeout); 5209 this._timeout = null; 5210 } // Static 5211 5212 5213 static jQueryInterface(config) { 5214 return this.each(function () { 5215 const data = Toast.getOrCreateInstance(this, config); 5216 5217 if (typeof config === 'string') { 5218 if (typeof data[config] === 'undefined') { 5219 throw new TypeError(`No method named "${config}"`); 5220 } 5221 5222 data[config](this); 5223 } 5224 }); 5225 } 5226 5227 } 5228 /** 5229 * Data API implementation 5230 */ 5231 5232 5233 enableDismissTrigger(Toast); 5234 /** 5235 * jQuery 5236 */ 5237 5238 defineJQueryPlugin(Toast); 5239 5240 /** 5241 * -------------------------------------------------------------------------- 5242 * Bootstrap (v5.2.1): index.umd.js 5243 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 5244 * -------------------------------------------------------------------------- 5245 */ 5246 const index_umd = { 5247 Alert, 5248 Button, 5249 Carousel, 5250 Collapse, 5251 Dropdown, 5252 Modal, 5253 Offcanvas, 5254 Popover, 5255 ScrollSpy, 5256 Tab, 5257 Toast, 5258 Tooltip 5259 }; 5260 5261 return index_umd; 5262 5263 })); 5264 //# sourceMappingURL=bootstrap.js.map