PluginProbe
UpdraftCentral Dashboard / trunk
UpdraftCentral Dashboard vtrunk
0.8.33 0.7.2 0.7.3 0.7.4 0.8.0 0.8.1 0.8.10 0.8.11 0.8.12 0.8.13 0.8.14 0.8.15 0.8.16 0.8.17 0.8.18 0.8.19 0.8.2 0.8.20 0.8.21 0.8.22 0.8.23 0.8.24 0.8.25 0.8.26 0.8.27 All 51 releases
updraftcentral / js / bootstrap / bootstrap.esm.js

bootstrap.esm.js in UpdraftCentral Dashboard trunk, at js/bootstrap/bootstrap.esm.js

4,448 lines 132.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 */
6 import * 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
19 const elementMap = new Map();
20 const 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
63 const MAX_UID = 1000000;
64 const MILLISECONDS_MULTIPLIER = 1000;
65 const TRANSITION_END = 'transitionend';
66
67 /**
68 * Properly escape IDs selectors to handle weird IDs
69 * @param {string} selector
70 * @returns {string}
71 */
72 const 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)
81 const 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
92 const getUID = prefix => {
93 do {
94 prefix += Math.floor(Math.random() * MAX_UID);
95 } while (document.getElementById(prefix));
96 return prefix;
97 };
98 const 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 };
121 const triggerTransitionEnd = element => {
122 element.dispatchEvent(new Event(TRANSITION_END));
123 };
124 const 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 };
133 const 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 };
143 const 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 };
164 const 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 };
176 const 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 };
196 const 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 */
206 const reflow = element => {
207 element.offsetHeight; // eslint-disable-line no-unused-expressions
208 };
209 const getjQuery = () => {
210 if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
211 return window.jQuery;
212 }
213 return null;
214 };
215 const DOMContentLoadedCallbacks = [];
216 const 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 };
231 const isRTL = () => document.documentElement.dir === 'rtl';
232 const 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 };
248 const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
249 return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue;
250 };
251 const 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 */
286 const 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
314 const namespaceRegex = /[^.]*(?=\..*)\.|.*/;
315 const stripNameRegex = /\..*/;
316 const stripUidRegex = /::\d+$/;
317 const eventRegistry = {}; // Events storage
318 let uidEvent = 1;
319 const customEvents = {
320 mouseenter: 'mouseover',
321 mouseleave: 'mouseout'
322 };
323 const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']);
324
325 /**
326 * Private methods
327 */
328
329 function makeEventUid(element, uid) {
330 return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++;
331 }
332 function getElementEvents(element) {
333 const uid = makeEventUid(element);
334 element.uidEvent = uid;
335 eventRegistry[uid] = eventRegistry[uid] || {};
336 return eventRegistry[uid];
337 }
338 function 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 }
349 function 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 }
370 function findHandler(events, callable, delegationSelector = null) {
371 return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector);
372 }
373 function 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 }
383 function 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 }
417 function 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 }
425 function 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 }
433 function 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 }
438 const 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 };
508 function 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
531 function 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 }
553 function normalizeDataKey(key) {
554 return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`);
555 }
556 const 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
593 class 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
646 const VERSION = '5.3.3';
647
648 /**
649 * Class definition
650 */
651
652 class 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
710 const 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 };
731 const 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
799 const 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
829 const NAME$f = 'alert';
830 const DATA_KEY$a = 'bs.alert';
831 const EVENT_KEY$b = `.${DATA_KEY$a}`;
832 const EVENT_CLOSE = `close${EVENT_KEY$b}`;
833 const EVENT_CLOSED = `closed${EVENT_KEY$b}`;
834 const CLASS_NAME_FADE$5 = 'fade';
835 const CLASS_NAME_SHOW$8 = 'show';
836
837 /**
838 * Class definition
839 */
840
841 class 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
884 enableDismissTrigger(Alert, 'close');
885
886 /**
887 * jQuery
888 */
889
890 defineJQueryPlugin(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
904 const NAME$e = 'button';
905 const DATA_KEY$9 = 'bs.button';
906 const EVENT_KEY$a = `.${DATA_KEY$9}`;
907 const DATA_API_KEY$6 = '.data-api';
908 const CLASS_NAME_ACTIVE$3 = 'active';
909 const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]';
910 const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`;
911
912 /**
913 * Class definition
914 */
915
916 class 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
943 EventHandler.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
954 defineJQueryPlugin(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
968 const NAME$d = 'swipe';
969 const EVENT_KEY$9 = '.bs.swipe';
970 const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`;
971 const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`;
972 const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`;
973 const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`;
974 const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`;
975 const POINTER_TYPE_TOUCH = 'touch';
976 const POINTER_TYPE_PEN = 'pen';
977 const CLASS_NAME_POINTER_EVENT = 'pointer-event';
978 const SWIPE_THRESHOLD = 40;
979 const Default$c = {
980 endCallback: null,
981 leftCallback: null,
982 rightCallback: null
983 };
984 const DefaultType$c = {
985 endCallback: '(function|null)',
986 leftCallback: '(function|null)',
987 rightCallback: '(function|null)'
988 };
989
990 /**
991 * Class definition
992 */
993
994 class 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
1088 const NAME$c = 'carousel';
1089 const DATA_KEY$8 = 'bs.carousel';
1090 const EVENT_KEY$8 = `.${DATA_KEY$8}`;
1091 const DATA_API_KEY$5 = '.data-api';
1092 const ARROW_LEFT_KEY$1 = 'ArrowLeft';
1093 const ARROW_RIGHT_KEY$1 = 'ArrowRight';
1094 const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
1095
1096 const ORDER_NEXT = 'next';
1097 const ORDER_PREV = 'prev';
1098 const DIRECTION_LEFT = 'left';
1099 const DIRECTION_RIGHT = 'right';
1100 const EVENT_SLIDE = `slide${EVENT_KEY$8}`;
1101 const EVENT_SLID = `slid${EVENT_KEY$8}`;
1102 const EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`;
1103 const EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`;
1104 const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`;
1105 const EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`;
1106 const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`;
1107 const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`;
1108 const CLASS_NAME_CAROUSEL = 'carousel';
1109 const CLASS_NAME_ACTIVE$2 = 'active';
1110 const CLASS_NAME_SLIDE = 'slide';
1111 const CLASS_NAME_END = 'carousel-item-end';
1112 const CLASS_NAME_START = 'carousel-item-start';
1113 const CLASS_NAME_NEXT = 'carousel-item-next';
1114 const CLASS_NAME_PREV = 'carousel-item-prev';
1115 const SELECTOR_ACTIVE = '.active';
1116 const SELECTOR_ITEM = '.carousel-item';
1117 const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM;
1118 const SELECTOR_ITEM_IMG = '.carousel-item img';
1119 const SELECTOR_INDICATORS = '.carousel-indicators';
1120 const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
1121 const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
1122 const KEY_TO_DIRECTION = {
1123 [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT,
1124 [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT
1125 };
1126 const Default$b = {
1127 interval: 5000,
1128 keyboard: true,
1129 pause: 'hover',
1130 ride: false,
1131 touch: true,
1132 wrap: true
1133 };
1134 const 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
1148 class 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
1415 EventHandler.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 });
1436 EventHandler.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
1447 defineJQueryPlugin(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
1461 const NAME$b = 'collapse';
1462 const DATA_KEY$7 = 'bs.collapse';
1463 const EVENT_KEY$7 = `.${DATA_KEY$7}`;
1464 const DATA_API_KEY$4 = '.data-api';
1465 const EVENT_SHOW$6 = `show${EVENT_KEY$7}`;
1466 const EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`;
1467 const EVENT_HIDE$6 = `hide${EVENT_KEY$7}`;
1468 const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`;
1469 const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`;
1470 const CLASS_NAME_SHOW$7 = 'show';
1471 const CLASS_NAME_COLLAPSE = 'collapse';
1472 const CLASS_NAME_COLLAPSING = 'collapsing';
1473 const CLASS_NAME_COLLAPSED = 'collapsed';
1474 const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;
1475 const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';
1476 const WIDTH = 'width';
1477 const HEIGHT = 'height';
1478 const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';
1479 const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]';
1480 const Default$a = {
1481 parent: null,
1482 toggle: true
1483 };
1484 const DefaultType$a = {
1485 parent: '(null|element)',
1486 toggle: 'boolean'
1487 };
1488
1489 /**
1490 * Class definition
1491 */
1492
1493 class 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
1665 EventHandler.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
1681 defineJQueryPlugin(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
1695 const NAME$a = 'dropdown';
1696 const DATA_KEY$6 = 'bs.dropdown';
1697 const EVENT_KEY$6 = `.${DATA_KEY$6}`;
1698 const DATA_API_KEY$3 = '.data-api';
1699 const ESCAPE_KEY$2 = 'Escape';
1700 const TAB_KEY$1 = 'Tab';
1701 const ARROW_UP_KEY$1 = 'ArrowUp';
1702 const ARROW_DOWN_KEY$1 = 'ArrowDown';
1703 const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button
1704
1705 const EVENT_HIDE$5 = `hide${EVENT_KEY$6}`;
1706 const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`;
1707 const EVENT_SHOW$5 = `show${EVENT_KEY$6}`;
1708 const EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`;
1709 const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`;
1710 const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`;
1711 const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`;
1712 const CLASS_NAME_SHOW$6 = 'show';
1713 const CLASS_NAME_DROPUP = 'dropup';
1714 const CLASS_NAME_DROPEND = 'dropend';
1715 const CLASS_NAME_DROPSTART = 'dropstart';
1716 const CLASS_NAME_DROPUP_CENTER = 'dropup-center';
1717 const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center';
1718 const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)';
1719 const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`;
1720 const SELECTOR_MENU = '.dropdown-menu';
1721 const SELECTOR_NAVBAR = '.navbar';
1722 const SELECTOR_NAVBAR_NAV = '.navbar-nav';
1723 const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
1724 const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start';
1725 const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end';
1726 const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start';
1727 const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end';
1728 const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start';
1729 const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start';
1730 const PLACEMENT_TOPCENTER = 'top';
1731 const PLACEMENT_BOTTOMCENTER = 'bottom';
1732 const Default$9 = {
1733 autoClose: true,
1734 boundary: 'clippingParents',
1735 display: 'dynamic',
1736 offset: [0, 2],
1737 popperConfig: null,
1738 reference: 'toggle'
1739 };
1740 const 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
1753 class 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
2036 EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);
2037 EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
2038 EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus);
2039 EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
2040 EventHandler.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
2049 defineJQueryPlugin(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
2063 const NAME$9 = 'backdrop';
2064 const CLASS_NAME_FADE$4 = 'fade';
2065 const CLASS_NAME_SHOW$5 = 'show';
2066 const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`;
2067 const 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 };
2075 const 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
2087 class 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
2187 const NAME$8 = 'focustrap';
2188 const DATA_KEY$5 = 'bs.focustrap';
2189 const EVENT_KEY$5 = `.${DATA_KEY$5}`;
2190 const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`;
2191 const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`;
2192 const TAB_KEY = 'Tab';
2193 const TAB_NAV_FORWARD = 'forward';
2194 const TAB_NAV_BACKWARD = 'backward';
2195 const Default$7 = {
2196 autofocus: true,
2197 trapElement: null // The element to trap focus inside of
2198 };
2199 const DefaultType$7 = {
2200 autofocus: 'boolean',
2201 trapElement: 'element'
2202 };
2203
2204 /**
2205 * Class definition
2206 */
2207
2208 class 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
2285 const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
2286 const SELECTOR_STICKY_CONTENT = '.sticky-top';
2287 const PROPERTY_PADDING = 'padding-right';
2288 const PROPERTY_MARGIN = 'margin-right';
2289
2290 /**
2291 * Class definition
2292 */
2293
2294 class 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
2383 const NAME$7 = 'modal';
2384 const DATA_KEY$4 = 'bs.modal';
2385 const EVENT_KEY$4 = `.${DATA_KEY$4}`;
2386 const DATA_API_KEY$2 = '.data-api';
2387 const ESCAPE_KEY$1 = 'Escape';
2388 const EVENT_HIDE$4 = `hide${EVENT_KEY$4}`;
2389 const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`;
2390 const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`;
2391 const EVENT_SHOW$4 = `show${EVENT_KEY$4}`;
2392 const EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`;
2393 const EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`;
2394 const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`;
2395 const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`;
2396 const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`;
2397 const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`;
2398 const CLASS_NAME_OPEN = 'modal-open';
2399 const CLASS_NAME_FADE$3 = 'fade';
2400 const CLASS_NAME_SHOW$4 = 'show';
2401 const CLASS_NAME_STATIC = 'modal-static';
2402 const OPEN_SELECTOR$1 = '.modal.show';
2403 const SELECTOR_DIALOG = '.modal-dialog';
2404 const SELECTOR_MODAL_BODY = '.modal-body';
2405 const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]';
2406 const Default$6 = {
2407 backdrop: true,
2408 focus: true,
2409 keyboard: true
2410 };
2411 const DefaultType$6 = {
2412 backdrop: '(boolean|string)',
2413 focus: 'boolean',
2414 keyboard: 'boolean'
2415 };
2416
2417 /**
2418 * Class definition
2419 */
2420
2421 class 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
2643 EventHandler.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 });
2668 enableDismissTrigger(Modal);
2669
2670 /**
2671 * jQuery
2672 */
2673
2674 defineJQueryPlugin(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
2688 const NAME$6 = 'offcanvas';
2689 const DATA_KEY$3 = 'bs.offcanvas';
2690 const EVENT_KEY$3 = `.${DATA_KEY$3}`;
2691 const DATA_API_KEY$1 = '.data-api';
2692 const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`;
2693 const ESCAPE_KEY = 'Escape';
2694 const CLASS_NAME_SHOW$3 = 'show';
2695 const CLASS_NAME_SHOWING$1 = 'showing';
2696 const CLASS_NAME_HIDING = 'hiding';
2697 const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
2698 const OPEN_SELECTOR = '.offcanvas.show';
2699 const EVENT_SHOW$3 = `show${EVENT_KEY$3}`;
2700 const EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`;
2701 const EVENT_HIDE$3 = `hide${EVENT_KEY$3}`;
2702 const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`;
2703 const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`;
2704 const EVENT_RESIZE = `resize${EVENT_KEY$3}`;
2705 const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`;
2706 const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`;
2707 const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]';
2708 const Default$5 = {
2709 backdrop: true,
2710 keyboard: true,
2711 scroll: false
2712 };
2713 const DefaultType$5 = {
2714 backdrop: '(boolean|string)',
2715 keyboard: 'boolean',
2716 scroll: 'boolean'
2717 };
2718
2719 /**
2720 * Class definition
2721 */
2722
2723 class 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
2864 EventHandler.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 });
2887 EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => {
2888 for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {
2889 Offcanvas.getOrCreateInstance(selector).show();
2890 }
2891 });
2892 EventHandler.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 });
2899 enableDismissTrigger(Offcanvas);
2900
2901 /**
2902 * jQuery
2903 */
2904
2905 defineJQueryPlugin(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
2915 const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
2916 const 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
2954 const 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
2963 const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;
2964 const 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 };
2976 function 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
3015 const NAME$5 = 'TemplateFactory';
3016 const 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 };
3026 const 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 };
3035 const DefaultContentType = {
3036 entry: '(string|element|function|null)',
3037 selector: '(string|element)'
3038 };
3039
3040 /**
3041 * Class definition
3042 */
3043
3044 class 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
3151 const NAME$4 = 'tooltip';
3152 const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
3153 const CLASS_NAME_FADE$2 = 'fade';
3154 const CLASS_NAME_MODAL = 'modal';
3155 const CLASS_NAME_SHOW$2 = 'show';
3156 const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
3157 const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
3158 const EVENT_MODAL_HIDE = 'hide.bs.modal';
3159 const TRIGGER_HOVER = 'hover';
3160 const TRIGGER_FOCUS = 'focus';
3161 const TRIGGER_CLICK = 'click';
3162 const TRIGGER_MANUAL = 'manual';
3163 const EVENT_HIDE$2 = 'hide';
3164 const EVENT_HIDDEN$2 = 'hidden';
3165 const EVENT_SHOW$2 = 'show';
3166 const EVENT_SHOWN$2 = 'shown';
3167 const EVENT_INSERTED = 'inserted';
3168 const EVENT_CLICK$1 = 'click';
3169 const EVENT_FOCUSIN$1 = 'focusin';
3170 const EVENT_FOCUSOUT$1 = 'focusout';
3171 const EVENT_MOUSEENTER = 'mouseenter';
3172 const EVENT_MOUSELEAVE = 'mouseleave';
3173 const AttachmentMap = {
3174 AUTO: 'auto',
3175 TOP: 'top',
3176 RIGHT: isRTL() ? 'left' : 'right',
3177 BOTTOM: 'bottom',
3178 LEFT: isRTL() ? 'right' : 'left'
3179 };
3180 const 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 };
3199 const 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
3223 class 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
3649 defineJQueryPlugin(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
3663 const NAME$3 = 'popover';
3664 const SELECTOR_TITLE = '.popover-header';
3665 const SELECTOR_CONTENT = '.popover-body';
3666 const 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 };
3674 const DefaultType$2 = {
3675 ...Tooltip.DefaultType,
3676 content: '(null|string|element|function)'
3677 };
3678
3679 /**
3680 * Class definition
3681 */
3682
3683 class 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
3730 defineJQueryPlugin(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
3744 const NAME$2 = 'scrollspy';
3745 const DATA_KEY$2 = 'bs.scrollspy';
3746 const EVENT_KEY$2 = `.${DATA_KEY$2}`;
3747 const DATA_API_KEY = '.data-api';
3748 const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`;
3749 const EVENT_CLICK = `click${EVENT_KEY$2}`;
3750 const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`;
3751 const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
3752 const CLASS_NAME_ACTIVE$1 = 'active';
3753 const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]';
3754 const SELECTOR_TARGET_LINKS = '[href]';
3755 const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
3756 const SELECTOR_NAV_LINKS = '.nav-link';
3757 const SELECTOR_NAV_ITEMS = '.nav-item';
3758 const SELECTOR_LIST_ITEMS = '.list-group-item';
3759 const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`;
3760 const SELECTOR_DROPDOWN = '.dropdown';
3761 const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';
3762 const 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 };
3770 const 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
3783 class 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
3980 EventHandler.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
3990 defineJQueryPlugin(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
4004 const NAME$1 = 'tab';
4005 const DATA_KEY$1 = 'bs.tab';
4006 const EVENT_KEY$1 = `.${DATA_KEY$1}`;
4007 const EVENT_HIDE$1 = `hide${EVENT_KEY$1}`;
4008 const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$1}`;
4009 const EVENT_SHOW$1 = `show${EVENT_KEY$1}`;
4010 const EVENT_SHOWN$1 = `shown${EVENT_KEY$1}`;
4011 const EVENT_CLICK_DATA_API = `click${EVENT_KEY$1}`;
4012 const EVENT_KEYDOWN = `keydown${EVENT_KEY$1}`;
4013 const EVENT_LOAD_DATA_API = `load${EVENT_KEY$1}`;
4014 const ARROW_LEFT_KEY = 'ArrowLeft';
4015 const ARROW_RIGHT_KEY = 'ArrowRight';
4016 const ARROW_UP_KEY = 'ArrowUp';
4017 const ARROW_DOWN_KEY = 'ArrowDown';
4018 const HOME_KEY = 'Home';
4019 const END_KEY = 'End';
4020 const CLASS_NAME_ACTIVE = 'active';
4021 const CLASS_NAME_FADE$1 = 'fade';
4022 const CLASS_NAME_SHOW$1 = 'show';
4023 const CLASS_DROPDOWN = 'dropdown';
4024 const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
4025 const SELECTOR_DROPDOWN_MENU = '.dropdown-menu';
4026 const NOT_SELECTOR_DROPDOWN_TOGGLE = `:not(${SELECTOR_DROPDOWN_TOGGLE})`;
4027 const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]';
4028 const SELECTOR_OUTER = '.nav-item, .list-group-item';
4029 const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`;
4030 const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'; // TODO: could only be `tab` in v6
4031 const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`;
4032 const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`;
4033
4034 /**
4035 * Class definition
4036 */
4037
4038 class 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
4238 EventHandler.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 */
4251 EventHandler.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
4260 defineJQueryPlugin(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
4274 const NAME = 'toast';
4275 const DATA_KEY = 'bs.toast';
4276 const EVENT_KEY = `.${DATA_KEY}`;
4277 const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
4278 const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
4279 const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
4280 const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`;
4281 const EVENT_HIDE = `hide${EVENT_KEY}`;
4282 const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
4283 const EVENT_SHOW = `show${EVENT_KEY}`;
4284 const EVENT_SHOWN = `shown${EVENT_KEY}`;
4285 const CLASS_NAME_FADE = 'fade';
4286 const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
4287 const CLASS_NAME_SHOW = 'show';
4288 const CLASS_NAME_SHOWING = 'showing';
4289 const DefaultType = {
4290 animation: 'boolean',
4291 autohide: 'boolean',
4292 delay: 'number'
4293 };
4294 const Default = {
4295 animation: true,
4296 autohide: true,
4297 delay: 5000
4298 };
4299
4300 /**
4301 * Class definition
4302 */
4303
4304 class 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
4438 enableDismissTrigger(Toast);
4439
4440 /**
4441 * jQuery
4442 */
4443
4444 defineJQueryPlugin(Toast);
4445
4446 export { Alert, Button, Carousel, Collapse, Dropdown, Modal, Offcanvas, Popover, ScrollSpy, Tab, Toast, Tooltip };
4447 //# sourceMappingURL=bootstrap.esm.js.map
4448