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