source: imaps-frontend/node_modules/bootstrap/dist/js/bootstrap.esm.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

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