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