diff options
author | Mario <mario@mariovavti.com> | 2021-11-09 09:10:19 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2021-11-09 09:10:19 +0000 |
commit | fe7ecede700fe04631d23f36473e697ce2b364dc (patch) | |
tree | e713fc39dba500a25cb2acf8561e286fb8b41ff0 /vendor/twbs/bootstrap/js/src | |
parent | 42de18d96d201d74e5df3ed1b8f6132cb00357b6 (diff) | |
parent | 089708ab9f90309a0c27ae633cf8f2604fce1170 (diff) | |
download | volse-hubzilla-fe7ecede700fe04631d23f36473e697ce2b364dc.tar.gz volse-hubzilla-fe7ecede700fe04631d23f36473e697ce2b364dc.tar.bz2 volse-hubzilla-fe7ecede700fe04631d23f36473e697ce2b364dc.zip |
Merge branch '6.4RC'6.4
Diffstat (limited to 'vendor/twbs/bootstrap/js/src')
23 files changed, 492 insertions, 469 deletions
diff --git a/vendor/twbs/bootstrap/js/src/alert.js b/vendor/twbs/bootstrap/js/src/alert.js index 75dbec71b..192bea89f 100644 --- a/vendor/twbs/bootstrap/js/src/alert.js +++ b/vendor/twbs/bootstrap/js/src/alert.js @@ -1,16 +1,14 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): alert.js + * Bootstrap (v5.1.3): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -import { - defineJQueryPlugin, - getElementFromSelector -} from './util/index' +import { defineJQueryPlugin } from './util/index' import EventHandler from './dom/event-handler' import BaseComponent from './base-component' +import { enableDismissTrigger } from './util/component-functions' /** * ------------------------------------------------------------------------ @@ -21,15 +19,9 @@ import BaseComponent from './base-component' const NAME = 'alert' const DATA_KEY = 'bs.alert' const EVENT_KEY = `.${DATA_KEY}` -const DATA_API_KEY = '.data-api' - -const SELECTOR_DISMISS = '[data-bs-dismiss="alert"]' const EVENT_CLOSE = `close${EVENT_KEY}` const EVENT_CLOSED = `closed${EVENT_KEY}` -const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` - -const CLASS_NAME_ALERT = 'alert' const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' @@ -48,38 +40,24 @@ class Alert extends BaseComponent { // Public - close(element) { - const rootElement = element ? this._getRootElement(element) : this._element - const customEvent = this._triggerCloseEvent(rootElement) + close() { + const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE) - if (customEvent === null || customEvent.defaultPrevented) { + if (closeEvent.defaultPrevented) { return } - this._removeElement(rootElement) - } - - // Private - - _getRootElement(element) { - return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`) - } - - _triggerCloseEvent(element) { - return EventHandler.trigger(element, EVENT_CLOSE) - } - - _removeElement(element) { - element.classList.remove(CLASS_NAME_SHOW) + this._element.classList.remove(CLASS_NAME_SHOW) - const isAnimated = element.classList.contains(CLASS_NAME_FADE) - this._queueCallback(() => this._destroyElement(element), element, isAnimated) + const isAnimated = this._element.classList.contains(CLASS_NAME_FADE) + this._queueCallback(() => this._destroyElement(), this._element, isAnimated) } - _destroyElement(element) { - element.remove() - - EventHandler.trigger(element, EVENT_CLOSED) + // Private + _destroyElement() { + this._element.remove() + EventHandler.trigger(this._element, EVENT_CLOSED) + this.dispose() } // Static @@ -88,20 +66,16 @@ class Alert extends BaseComponent { return this.each(function () { const data = Alert.getOrCreateInstance(this) - if (config === 'close') { - data[config](this) + if (typeof config !== 'string') { + return } - }) - } - static handleDismiss(alertInstance) { - return function (event) { - if (event) { - event.preventDefault() + if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { + throw new TypeError(`No method named "${config}"`) } - alertInstance.close(this) - } + data[config](this) + }) } } @@ -111,7 +85,7 @@ class Alert extends BaseComponent { * ------------------------------------------------------------------------ */ -EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DISMISS, Alert.handleDismiss(new Alert())) +enableDismissTrigger(Alert, 'close') /** * ------------------------------------------------------------------------ diff --git a/vendor/twbs/bootstrap/js/src/base-component.js b/vendor/twbs/bootstrap/js/src/base-component.js index 62aa4adf1..28cf877fb 100644 --- a/vendor/twbs/bootstrap/js/src/base-component.js +++ b/vendor/twbs/bootstrap/js/src/base-component.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): base-component.js + * Bootstrap (v5.1.3): base-component.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -18,7 +18,7 @@ import EventHandler from './dom/event-handler' * ------------------------------------------------------------------------ */ -const VERSION = '5.0.2' +const VERSION = '5.1.3' class BaseComponent { constructor(element) { @@ -48,7 +48,7 @@ class BaseComponent { /** Static */ static getInstance(element) { - return Data.get(element, this.DATA_KEY) + return Data.get(getElement(element), this.DATA_KEY) } static getOrCreateInstance(element, config = {}) { diff --git a/vendor/twbs/bootstrap/js/src/button.js b/vendor/twbs/bootstrap/js/src/button.js index 528f6233c..82d1b87db 100644 --- a/vendor/twbs/bootstrap/js/src/button.js +++ b/vendor/twbs/bootstrap/js/src/button.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): button.js + * Bootstrap (v5.1.3): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ diff --git a/vendor/twbs/bootstrap/js/src/carousel.js b/vendor/twbs/bootstrap/js/src/carousel.js index fe43f53eb..2cb71dcaa 100644 --- a/vendor/twbs/bootstrap/js/src/carousel.js +++ b/vendor/twbs/bootstrap/js/src/carousel.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): carousel.js + * Bootstrap (v5.1.3): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -260,8 +260,13 @@ class Carousel extends BaseComponent { } _addTouchEventListeners() { + const hasPointerPenTouch = event => { + return this._pointerEvent && + (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH) + } + const start = event => { - if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) { + if (hasPointerPenTouch(event)) { this.touchStartX = event.clientX } else if (!this._pointerEvent) { this.touchStartX = event.touches[0].clientX @@ -276,7 +281,7 @@ class Carousel extends BaseComponent { } const end = event => { - if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) { + if (hasPointerPenTouch(event)) { this.touchDeltaX = event.clientX - this.touchStartX } @@ -300,7 +305,7 @@ class Carousel extends BaseComponent { } SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => { - EventHandler.on(itemImg, EVENT_DRAG_START, e => e.preventDefault()) + EventHandler.on(itemImg, EVENT_DRAG_START, event => event.preventDefault()) }) if (this._pointerEvent) { diff --git a/vendor/twbs/bootstrap/js/src/collapse.js b/vendor/twbs/bootstrap/js/src/collapse.js index 8831510df..33d5674eb 100644 --- a/vendor/twbs/bootstrap/js/src/collapse.js +++ b/vendor/twbs/bootstrap/js/src/collapse.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): collapse.js + * Bootstrap (v5.1.3): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -32,12 +32,12 @@ const DATA_API_KEY = '.data-api' const Default = { toggle: true, - parent: '' + parent: null } const DefaultType = { toggle: 'boolean', - parent: '(string|element)' + parent: '(null|element)' } const EVENT_SHOW = `show${EVENT_KEY}` @@ -50,11 +50,13 @@ const CLASS_NAME_SHOW = 'show' const CLASS_NAME_COLLAPSE = 'collapse' const CLASS_NAME_COLLAPSING = 'collapsing' const CLASS_NAME_COLLAPSED = 'collapsed' +const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}` +const CLASS_NAME_HORIZONTAL = 'collapse-horizontal' const WIDTH = 'width' const HEIGHT = 'height' -const SELECTOR_ACTIVES = '.show, .collapsing' +const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="collapse"]' /** @@ -69,10 +71,7 @@ class Collapse extends BaseComponent { this._isTransitioning = false this._config = this._getConfig(config) - this._triggerArray = SelectorEngine.find( - `${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"],` + - `${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]` - ) + this._triggerArray = [] const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE) @@ -88,10 +87,10 @@ class Collapse extends BaseComponent { } } - this._parent = this._config.parent ? this._getParent() : null + this._initializeChildren() if (!this._config.parent) { - this._addAriaAndCollapsedClass(this._element, this._triggerArray) + this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()) } if (this._config.toggle) { @@ -112,7 +111,7 @@ class Collapse extends BaseComponent { // Public toggle() { - if (this._element.classList.contains(CLASS_NAME_SHOW)) { + if (this._isShown()) { this.hide() } else { this.show() @@ -120,30 +119,20 @@ class Collapse extends BaseComponent { } show() { - if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW)) { + if (this._isTransitioning || this._isShown()) { return } - let actives + let actives = [] let activesData - if (this._parent) { - actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent) - .filter(elem => { - if (typeof this._config.parent === 'string') { - return elem.getAttribute('data-bs-parent') === this._config.parent - } - - return elem.classList.contains(CLASS_NAME_COLLAPSE) - }) - - if (actives.length === 0) { - actives = null - } + if (this._config.parent) { + const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent) + actives = SelectorEngine.find(SELECTOR_ACTIVES, this._config.parent).filter(elem => !children.includes(elem)) // remove children if greater depth } const container = SelectorEngine.findOne(this._selector) - if (actives) { + if (actives.length) { const tempActiveData = actives.find(elem => container !== elem) activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null @@ -157,17 +146,15 @@ class Collapse extends BaseComponent { return } - if (actives) { - actives.forEach(elemActive => { - if (container !== elemActive) { - Collapse.collapseInterface(elemActive, 'hide') - } + actives.forEach(elemActive => { + if (container !== elemActive) { + Collapse.getOrCreateInstance(elemActive, { toggle: false }).hide() + } - if (!activesData) { - Data.set(elemActive, DATA_KEY, null) - } - }) - } + if (!activesData) { + Data.set(elemActive, DATA_KEY, null) + } + }) const dimension = this._getDimension() @@ -176,23 +163,17 @@ class Collapse extends BaseComponent { this._element.style[dimension] = 0 - if (this._triggerArray.length) { - this._triggerArray.forEach(element => { - element.classList.remove(CLASS_NAME_COLLAPSED) - element.setAttribute('aria-expanded', true) - }) - } - - this.setTransitioning(true) + this._addAriaAndCollapsedClass(this._triggerArray, true) + this._isTransitioning = true const complete = () => { + this._isTransitioning = false + this._element.classList.remove(CLASS_NAME_COLLAPSING) this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW) this._element.style[dimension] = '' - this.setTransitioning(false) - EventHandler.trigger(this._element, EVENT_SHOWN) } @@ -204,7 +185,7 @@ class Collapse extends BaseComponent { } hide() { - if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW)) { + if (this._isTransitioning || !this._isShown()) { return } @@ -223,22 +204,19 @@ class Collapse extends BaseComponent { this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW) const triggerArrayLength = this._triggerArray.length - if (triggerArrayLength > 0) { - for (let i = 0; i < triggerArrayLength; i++) { - const trigger = this._triggerArray[i] - const elem = getElementFromSelector(trigger) - - if (elem && !elem.classList.contains(CLASS_NAME_SHOW)) { - trigger.classList.add(CLASS_NAME_COLLAPSED) - trigger.setAttribute('aria-expanded', false) - } + for (let i = 0; i < triggerArrayLength; i++) { + const trigger = this._triggerArray[i] + const elem = getElementFromSelector(trigger) + + if (elem && !this._isShown(elem)) { + this._addAriaAndCollapsedClass([trigger], false) } } - this.setTransitioning(true) + this._isTransitioning = true const complete = () => { - this.setTransitioning(false) + this._isTransitioning = false this._element.classList.remove(CLASS_NAME_COLLAPSING) this._element.classList.add(CLASS_NAME_COLLAPSE) EventHandler.trigger(this._element, EVENT_HIDDEN) @@ -249,8 +227,8 @@ class Collapse extends BaseComponent { this._queueCallback(complete, this._element, true) } - setTransitioning(isTransitioning) { - this._isTransitioning = isTransitioning + _isShown(element = this._element) { + return element.classList.contains(CLASS_NAME_SHOW) } // Private @@ -258,44 +236,40 @@ class Collapse extends BaseComponent { _getConfig(config) { config = { ...Default, + ...Manipulator.getDataAttributes(this._element), ...config } config.toggle = Boolean(config.toggle) // Coerce string values + config.parent = getElement(config.parent) typeCheckConfig(NAME, config, DefaultType) return config } _getDimension() { - return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT + return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT } - _getParent() { - let { parent } = this._config - - parent = getElement(parent) - - const selector = `${SELECTOR_DATA_TOGGLE}[data-bs-parent="${parent}"]` + _initializeChildren() { + if (!this._config.parent) { + return + } - SelectorEngine.find(selector, parent) + const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent) + SelectorEngine.find(SELECTOR_DATA_TOGGLE, this._config.parent).filter(elem => !children.includes(elem)) .forEach(element => { const selected = getElementFromSelector(element) - this._addAriaAndCollapsedClass( - selected, - [element] - ) + if (selected) { + this._addAriaAndCollapsedClass([element], this._isShown(selected)) + } }) - - return parent } - _addAriaAndCollapsedClass(element, triggerArray) { - if (!element || !triggerArray.length) { + _addAriaAndCollapsedClass(triggerArray, isOpen) { + if (!triggerArray.length) { return } - const isOpen = element.classList.contains(CLASS_NAME_SHOW) - triggerArray.forEach(elem => { if (isOpen) { elem.classList.remove(CLASS_NAME_COLLAPSED) @@ -309,34 +283,22 @@ class Collapse extends BaseComponent { // Static - static collapseInterface(element, config) { - let data = Collapse.getInstance(element) - const _config = { - ...Default, - ...Manipulator.getDataAttributes(element), - ...(typeof config === 'object' && config ? config : {}) - } + static jQueryInterface(config) { + return this.each(function () { + const _config = {} + if (typeof config === 'string' && /show|hide/.test(config)) { + _config.toggle = false + } - if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) { - _config.toggle = false - } + const data = Collapse.getOrCreateInstance(this, _config) - if (!data) { - data = new Collapse(element, _config) - } + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError(`No method named "${config}"`) + } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError(`No method named "${config}"`) + data[config]() } - - data[config]() - } - } - - static jQueryInterface(config) { - return this.each(function () { - Collapse.collapseInterface(this, config) }) } } @@ -353,26 +315,11 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( event.preventDefault() } - const triggerData = Manipulator.getDataAttributes(this) const selector = getSelectorFromElement(this) const selectorElements = SelectorEngine.find(selector) selectorElements.forEach(element => { - const data = Collapse.getInstance(element) - let config - if (data) { - // update parent attribute - if (data._parent === null && typeof triggerData.parent === 'string') { - data._config.parent = triggerData.parent - data._parent = data._getParent() - } - - config = 'toggle' - } else { - config = triggerData - } - - Collapse.collapseInterface(element, config) + Collapse.getOrCreateInstance(element, { toggle: false }).toggle() }) }) diff --git a/vendor/twbs/bootstrap/js/src/dom/data.js b/vendor/twbs/bootstrap/js/src/dom/data.js index cb88ef53d..c702fc82c 100644 --- a/vendor/twbs/bootstrap/js/src/dom/data.js +++ b/vendor/twbs/bootstrap/js/src/dom/data.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): dom/data.js + * Bootstrap (v5.1.3): dom/data.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ diff --git a/vendor/twbs/bootstrap/js/src/dom/event-handler.js b/vendor/twbs/bootstrap/js/src/dom/event-handler.js index c8303f7f2..e085ea138 100644 --- a/vendor/twbs/bootstrap/js/src/dom/event-handler.js +++ b/vendor/twbs/bootstrap/js/src/dom/event-handler.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): dom/event-handler.js + * Bootstrap (v5.1.3): dom/event-handler.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -113,7 +113,6 @@ function bootstrapDelegationHandler(element, selector, fn) { event.delegateTarget = target if (handler.oneOff) { - // eslint-disable-next-line unicorn/consistent-destructuring EventHandler.off(element, event.type, selector, fn) } diff --git a/vendor/twbs/bootstrap/js/src/dom/manipulator.js b/vendor/twbs/bootstrap/js/src/dom/manipulator.js index 113817bee..04982d63e 100644 --- a/vendor/twbs/bootstrap/js/src/dom/manipulator.js +++ b/vendor/twbs/bootstrap/js/src/dom/manipulator.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): dom/manipulator.js + * Bootstrap (v5.1.3): dom/manipulator.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -64,8 +64,8 @@ const Manipulator = { const rect = element.getBoundingClientRect() return { - top: rect.top + document.body.scrollTop, - left: rect.left + document.body.scrollLeft + top: rect.top + window.pageYOffset, + left: rect.left + window.pageXOffset } }, diff --git a/vendor/twbs/bootstrap/js/src/dom/selector-engine.js b/vendor/twbs/bootstrap/js/src/dom/selector-engine.js index 381e45fe8..54f270f4c 100644 --- a/vendor/twbs/bootstrap/js/src/dom/selector-engine.js +++ b/vendor/twbs/bootstrap/js/src/dom/selector-engine.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): dom/selector-engine.js + * Bootstrap (v5.1.3): dom/selector-engine.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -11,6 +11,8 @@ * ------------------------------------------------------------------------ */ +import { isDisabled, isVisible } from '../util/index' + const NODE_TEXT = 3 const SelectorEngine = { @@ -69,6 +71,21 @@ const SelectorEngine = { } return [] + }, + + focusableChildren(element) { + const focusables = [ + 'a', + 'button', + 'input', + 'textarea', + 'select', + 'details', + '[tabindex]', + '[contenteditable="true"]' + ].map(selector => `${selector}:not([tabindex^="-"])`).join(', ') + + return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)) } } diff --git a/vendor/twbs/bootstrap/js/src/dropdown.js b/vendor/twbs/bootstrap/js/src/dropdown.js index 681369b48..6fafdb116 100644 --- a/vendor/twbs/bootstrap/js/src/dropdown.js +++ b/vendor/twbs/bootstrap/js/src/dropdown.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): dropdown.js + * Bootstrap (v5.1.3): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -11,12 +11,12 @@ import { defineJQueryPlugin, getElement, getElementFromSelector, + getNextActiveElement, isDisabled, isElement, - isVisible, isRTL, + isVisible, noop, - getNextActiveElement, typeCheckConfig } from './util/index' import EventHandler from './dom/event-handler' @@ -48,7 +48,6 @@ const EVENT_HIDE = `hide${EVENT_KEY}` const EVENT_HIDDEN = `hidden${EVENT_KEY}` const EVENT_SHOW = `show${EVENT_KEY}` const EVENT_SHOWN = `shown${EVENT_KEY}` -const EVENT_CLICK = `click${EVENT_KEY}` const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}${DATA_API_KEY}` const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}${DATA_API_KEY}` @@ -103,8 +102,6 @@ class Dropdown extends BaseComponent { this._config = this._getConfig(config) this._menu = this._getMenuElement() this._inNavbar = this._detectNavbar() - - this._addEventListeners() } // Getters @@ -124,26 +121,14 @@ class Dropdown extends BaseComponent { // Public toggle() { - if (isDisabled(this._element)) { - return - } - - const isActive = this._element.classList.contains(CLASS_NAME_SHOW) - - if (isActive) { - this.hide() - return - } - - this.show() + return this._isShown() ? this.hide() : this.show() } show() { - if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW)) { + if (isDisabled(this._element) || this._isShown(this._menu)) { return } - const parent = Dropdown.getParentFromElement(this._element) const relatedTarget = { relatedTarget: this._element } @@ -154,32 +139,12 @@ class Dropdown extends BaseComponent { return } + const parent = Dropdown.getParentFromElement(this._element) // Totally disable Popper for Dropdowns in Navbar if (this._inNavbar) { Manipulator.setDataAttribute(this._menu, 'popper', 'none') } else { - if (typeof Popper === 'undefined') { - throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)') - } - - let referenceElement = this._element - - if (this._config.reference === 'parent') { - referenceElement = parent - } else if (isElement(this._config.reference)) { - referenceElement = getElement(this._config.reference) - } else if (typeof this._config.reference === 'object') { - referenceElement = this._config.reference - } - - const popperConfig = this._getPopperConfig() - const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false) - - this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig) - - if (isDisplayStatic) { - Manipulator.setDataAttribute(this._menu, 'popper', 'static') - } + this._createPopper(parent) } // If this is a touch-enabled device we add extra @@ -195,13 +160,13 @@ class Dropdown extends BaseComponent { this._element.focus() this._element.setAttribute('aria-expanded', true) - this._menu.classList.toggle(CLASS_NAME_SHOW) - this._element.classList.toggle(CLASS_NAME_SHOW) + this._menu.classList.add(CLASS_NAME_SHOW) + this._element.classList.add(CLASS_NAME_SHOW) EventHandler.trigger(this._element, EVENT_SHOWN, relatedTarget) } hide() { - if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW)) { + if (isDisabled(this._element) || !this._isShown(this._menu)) { return } @@ -229,13 +194,6 @@ class Dropdown extends BaseComponent { // Private - _addEventListeners() { - EventHandler.on(this._element, EVENT_CLICK, event => { - event.preventDefault() - this.toggle() - }) - } - _completeHide(relatedTarget) { const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE, relatedTarget) if (hideEvent.defaultPrevented) { @@ -279,6 +237,35 @@ class Dropdown extends BaseComponent { return config } + _createPopper(parent) { + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)') + } + + let referenceElement = this._element + + if (this._config.reference === 'parent') { + referenceElement = parent + } else if (isElement(this._config.reference)) { + referenceElement = getElement(this._config.reference) + } else if (typeof this._config.reference === 'object') { + referenceElement = this._config.reference + } + + const popperConfig = this._getPopperConfig() + const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false) + + this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig) + + if (isDisplayStatic) { + Manipulator.setDataAttribute(this._menu, 'popper', 'static') + } + } + + _isShown(element = this._element) { + return element.classList.contains(CLASS_NAME_SHOW) + } + _getMenuElement() { return SelectorEngine.next(this._element, SELECTOR_MENU)[0] } @@ -367,21 +354,19 @@ class Dropdown extends BaseComponent { // Static - static dropdownInterface(element, config) { - const data = Dropdown.getOrCreateInstance(element, config) + static jQueryInterface(config) { + return this.each(function () { + const data = Dropdown.getOrCreateInstance(this, config) + + if (typeof config !== 'string') { + return + } - if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`) } data[config]() - } - } - - static jQueryInterface(config) { - return this.each(function () { - Dropdown.dropdownInterface(this, config) }) } @@ -398,7 +383,7 @@ class Dropdown extends BaseComponent { continue } - if (!context._element.classList.contains(CLASS_NAME_SHOW)) { + if (!context._isShown()) { continue } @@ -464,20 +449,20 @@ class Dropdown extends BaseComponent { return } - const getToggleButton = () => this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] + const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE)[0] + const instance = Dropdown.getOrCreateInstance(getToggleButton) if (event.key === ESCAPE_KEY) { - getToggleButton().focus() - Dropdown.clearMenus() + instance.hide() return } if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) { if (!isActive) { - getToggleButton().click() + instance.show() } - Dropdown.getInstance(getToggleButton())._selectMenuItem(event) + instance._selectMenuItem(event) return } @@ -499,7 +484,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, Dropdown.clearMenus) EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus) EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { event.preventDefault() - Dropdown.dropdownInterface(this) + Dropdown.getOrCreateInstance(this).toggle() }) /** diff --git a/vendor/twbs/bootstrap/js/src/modal.js b/vendor/twbs/bootstrap/js/src/modal.js index 8dac75265..00df5c482 100644 --- a/vendor/twbs/bootstrap/js/src/modal.js +++ b/vendor/twbs/bootstrap/js/src/modal.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): modal.js + * Bootstrap (v5.1.3): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -19,6 +19,8 @@ import SelectorEngine from './dom/selector-engine' import ScrollBarHelper from './util/scrollbar' import BaseComponent from './base-component' import Backdrop from './util/backdrop' +import FocusTrap from './util/focustrap' +import { enableDismissTrigger } from './util/component-functions' /** * ------------------------------------------------------------------------ @@ -49,7 +51,6 @@ const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}` const EVENT_HIDDEN = `hidden${EVENT_KEY}` const EVENT_SHOW = `show${EVENT_KEY}` const EVENT_SHOWN = `shown${EVENT_KEY}` -const EVENT_FOCUSIN = `focusin${EVENT_KEY}` const EVENT_RESIZE = `resize${EVENT_KEY}` const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}` const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}` @@ -62,10 +63,10 @@ const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' const CLASS_NAME_STATIC = 'modal-static' +const OPEN_SELECTOR = '.modal.show' const SELECTOR_DIALOG = '.modal-dialog' const SELECTOR_MODAL_BODY = '.modal-body' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="modal"]' -const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="modal"]' /** * ------------------------------------------------------------------------ @@ -80,6 +81,7 @@ class Modal extends BaseComponent { this._config = this._getConfig(config) this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element) this._backdrop = this._initializeBackDrop() + this._focustrap = this._initializeFocusTrap() this._isShown = false this._ignoreBackdropClick = false this._isTransitioning = false @@ -130,8 +132,6 @@ class Modal extends BaseComponent { this._setEscapeEvent() this._setResizeEvent() - EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, event => this.hide(event)) - EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, event => { if (event.target === this._element) { @@ -143,11 +143,7 @@ class Modal extends BaseComponent { this._showBackdrop(() => this._showElement(relatedTarget)) } - hide(event) { - if (event && ['A', 'AREA'].includes(event.target.tagName)) { - event.preventDefault() - } - + hide() { if (!this._isShown || this._isTransitioning) { return } @@ -168,7 +164,7 @@ class Modal extends BaseComponent { this._setEscapeEvent() this._setResizeEvent() - EventHandler.off(document, EVENT_FOCUSIN) + this._focustrap.deactivate() this._element.classList.remove(CLASS_NAME_SHOW) @@ -183,14 +179,8 @@ class Modal extends BaseComponent { .forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY)) this._backdrop.dispose() + this._focustrap.deactivate() super.dispose() - - /** - * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API` - * Do not move `document` in `htmlElements` array - * It will remove `EVENT_CLICK_DATA_API` event that should remain - */ - EventHandler.off(document, EVENT_FOCUSIN) } handleUpdate() { @@ -206,6 +196,12 @@ class Modal extends BaseComponent { }) } + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element + }) + } + _getConfig(config) { config = { ...Default, @@ -222,7 +218,7 @@ class Modal extends BaseComponent { if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { // Don't move modal's DOM position - document.body.appendChild(this._element) + document.body.append(this._element) } this._element.style.display = 'block' @@ -241,13 +237,9 @@ class Modal extends BaseComponent { this._element.classList.add(CLASS_NAME_SHOW) - if (this._config.focus) { - this._enforceFocus() - } - const transitionComplete = () => { if (this._config.focus) { - this._element.focus() + this._focustrap.activate() } this._isTransitioning = false @@ -259,17 +251,6 @@ class Modal extends BaseComponent { this._queueCallback(transitionComplete, this._dialog, isAnimated) } - _enforceFocus() { - EventHandler.off(document, EVENT_FOCUSIN) // guard against infinite focus loop - EventHandler.on(document, EVENT_FOCUSIN, event => { - if (document !== event.target && - this._element !== event.target && - !this._element.contains(event.target)) { - this._element.focus() - } - }) - } - _setEscapeEvent() { if (this._isShown) { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { @@ -431,11 +412,19 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( }) }) + // avoid conflict when clicking moddal toggler while another one is open + const allReadyOpen = SelectorEngine.findOne(OPEN_SELECTOR) + if (allReadyOpen) { + Modal.getInstance(allReadyOpen).hide() + } + const data = Modal.getOrCreateInstance(target) data.toggle(this) }) +enableDismissTrigger(Modal) + /** * ------------------------------------------------------------------------ * jQuery diff --git a/vendor/twbs/bootstrap/js/src/offcanvas.js b/vendor/twbs/bootstrap/js/src/offcanvas.js index 88eb8c997..66378fd23 100644 --- a/vendor/twbs/bootstrap/js/src/offcanvas.js +++ b/vendor/twbs/bootstrap/js/src/offcanvas.js @@ -1,7 +1,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): offcanvas.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Bootstrap (v5.1.3): offcanvas.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -18,6 +18,8 @@ import BaseComponent from './base-component' import SelectorEngine from './dom/selector-engine' import Manipulator from './dom/manipulator' import Backdrop from './util/backdrop' +import FocusTrap from './util/focustrap' +import { enableDismissTrigger } from './util/component-functions' /** * ------------------------------------------------------------------------ @@ -45,18 +47,16 @@ const DefaultType = { } const CLASS_NAME_SHOW = 'show' +const CLASS_NAME_BACKDROP = 'offcanvas-backdrop' const OPEN_SELECTOR = '.offcanvas.show' const EVENT_SHOW = `show${EVENT_KEY}` const EVENT_SHOWN = `shown${EVENT_KEY}` const EVENT_HIDE = `hide${EVENT_KEY}` const EVENT_HIDDEN = `hidden${EVENT_KEY}` -const EVENT_FOCUSIN = `focusin${EVENT_KEY}` const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}` const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}` -const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="offcanvas"]' const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="offcanvas"]' /** @@ -72,6 +72,7 @@ class Offcanvas extends BaseComponent { this._config = this._getConfig(config) this._isShown = false this._backdrop = this._initializeBackDrop() + this._focustrap = this._initializeFocusTrap() this._addEventListeners() } @@ -109,7 +110,6 @@ class Offcanvas extends BaseComponent { if (!this._config.scroll) { new ScrollBarHelper().hide() - this._enforceFocusOnElement(this._element) } this._element.removeAttribute('aria-hidden') @@ -118,6 +118,10 @@ class Offcanvas extends BaseComponent { this._element.classList.add(CLASS_NAME_SHOW) const completeCallBack = () => { + if (!this._config.scroll) { + this._focustrap.activate() + } + EventHandler.trigger(this._element, EVENT_SHOWN, { relatedTarget }) } @@ -135,7 +139,7 @@ class Offcanvas extends BaseComponent { return } - EventHandler.off(document, EVENT_FOCUSIN) + this._focustrap.deactivate() this._element.blur() this._isShown = false this._element.classList.remove(CLASS_NAME_SHOW) @@ -159,8 +163,8 @@ class Offcanvas extends BaseComponent { dispose() { this._backdrop.dispose() + this._focustrap.deactivate() super.dispose() - EventHandler.off(document, EVENT_FOCUSIN) } // Private @@ -177,6 +181,7 @@ class Offcanvas extends BaseComponent { _initializeBackDrop() { return new Backdrop({ + className: CLASS_NAME_BACKDROP, isVisible: this._config.backdrop, isAnimated: true, rootElement: this._element.parentNode, @@ -184,21 +189,13 @@ class Offcanvas extends BaseComponent { }) } - _enforceFocusOnElement(element) { - EventHandler.off(document, EVENT_FOCUSIN) // guard against infinite focus loop - EventHandler.on(document, EVENT_FOCUSIN, event => { - if (document !== event.target && - element !== event.target && - !element.contains(event.target)) { - element.focus() - } + _initializeFocusTrap() { + return new FocusTrap({ + trapElement: this._element }) - element.focus() } _addEventListeners() { - EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide()) - EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { if (this._config.keyboard && event.key === ESCAPE_KEY) { this.hide() @@ -263,6 +260,7 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show()) ) +enableDismissTrigger(Offcanvas) /** * ------------------------------------------------------------------------ * jQuery diff --git a/vendor/twbs/bootstrap/js/src/popover.js b/vendor/twbs/bootstrap/js/src/popover.js index 5a3b32631..aa9b0bc9e 100644 --- a/vendor/twbs/bootstrap/js/src/popover.js +++ b/vendor/twbs/bootstrap/js/src/popover.js @@ -1,12 +1,11 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): popover.js + * Bootstrap (v5.1.3): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ import { defineJQueryPlugin } from './util/index' -import SelectorEngine from './dom/selector-engine' import Tooltip from './tooltip' /** @@ -19,7 +18,6 @@ const NAME = 'popover' const DATA_KEY = 'bs.popover' const EVENT_KEY = `.${DATA_KEY}` const CLASS_PREFIX = 'bs-popover' -const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') const Default = { ...Tooltip.Default, @@ -52,9 +50,6 @@ const Event = { MOUSELEAVE: `mouseleave${EVENT_KEY}` } -const CLASS_NAME_FADE = 'fade' -const CLASS_NAME_SHOW = 'show' - const SELECTOR_TITLE = '.popover-header' const SELECTOR_CONTENT = '.popover-body' @@ -89,56 +84,19 @@ class Popover extends Tooltip { return this.getTitle() || this._getContent() } - getTipElement() { - if (this.tip) { - return this.tip - } - - this.tip = super.getTipElement() - - if (!this.getTitle()) { - SelectorEngine.findOne(SELECTOR_TITLE, this.tip).remove() - } - - if (!this._getContent()) { - SelectorEngine.findOne(SELECTOR_CONTENT, this.tip).remove() - } - - return this.tip - } - - setContent() { - const tip = this.getTipElement() - - // we use append for html objects to maintain js events - this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle()) - let content = this._getContent() - if (typeof content === 'function') { - content = content.call(this._element) - } - - this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content) - - tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW) + setContent(tip) { + this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TITLE) + this._sanitizeAndSetContent(tip, this._getContent(), SELECTOR_CONTENT) } // Private - _addAttachmentClass(attachment) { - this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`) - } - _getContent() { - return this._element.getAttribute('data-bs-content') || this._config.content + return this._resolvePossibleFunction(this._config.content) } - _cleanTipClass() { - const tip = this.getTipElement() - const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX) - if (tabClass !== null && tabClass.length > 0) { - tabClass.map(token => token.trim()) - .forEach(tClass => tip.classList.remove(tClass)) - } + _getBasicClassPrefix() { + return CLASS_PREFIX } // Static diff --git a/vendor/twbs/bootstrap/js/src/scrollspy.js b/vendor/twbs/bootstrap/js/src/scrollspy.js index e2c432ca3..825b07fbc 100644 --- a/vendor/twbs/bootstrap/js/src/scrollspy.js +++ b/vendor/twbs/bootstrap/js/src/scrollspy.js @@ -1,15 +1,14 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): scrollspy.js + * Bootstrap (v5.1.3): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ import { defineJQueryPlugin, + getElement, getSelectorFromElement, - getUID, - isElement, typeCheckConfig } from './util/index' import EventHandler from './dom/event-handler' @@ -52,6 +51,7 @@ const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group' const SELECTOR_NAV_LINKS = '.nav-link' const SELECTOR_NAV_ITEMS = '.nav-item' const SELECTOR_LIST_ITEMS = '.list-group-item' +const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}, .${CLASS_NAME_DROPDOWN_ITEM}` const SELECTOR_DROPDOWN = '.dropdown' const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle' @@ -69,7 +69,6 @@ class ScrollSpy extends BaseComponent { super(element) this._scrollElement = this._element.tagName === 'BODY' ? window : this._element this._config = this._getConfig(config) - this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}` this._offsets = [] this._targets = [] this._activeTarget = null @@ -110,7 +109,7 @@ class ScrollSpy extends BaseComponent { this._targets = [] this._scrollHeight = this._getScrollHeight() - const targets = SelectorEngine.find(this._selector) + const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target) targets.map(element => { const targetSelector = getSelectorFromElement(element) @@ -150,15 +149,7 @@ class ScrollSpy extends BaseComponent { ...(typeof config === 'object' && config ? config : {}) } - if (typeof config.target !== 'string' && isElement(config.target)) { - let { id } = config.target - if (!id) { - id = getUID(NAME) - config.target.id = id - } - - config.target = `#${id}` - } + config.target = getElement(config.target) || document.documentElement typeCheckConfig(NAME, config, DefaultType) @@ -225,20 +216,16 @@ class ScrollSpy extends BaseComponent { this._clear() - const queries = this._selector.split(',') + const queries = SELECTOR_LINK_ITEMS.split(',') .map(selector => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`) - const link = SelectorEngine.findOne(queries.join(',')) + const link = SelectorEngine.findOne(queries.join(','), this._config.target) + link.classList.add(CLASS_NAME_ACTIVE) if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN)) .classList.add(CLASS_NAME_ACTIVE) - - link.classList.add(CLASS_NAME_ACTIVE) } else { - // Set triggered link as active - link.classList.add(CLASS_NAME_ACTIVE) - SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP) .forEach(listGroup => { // Set triggered links parents as active @@ -261,7 +248,7 @@ class ScrollSpy extends BaseComponent { } _clear() { - SelectorEngine.find(this._selector) + SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target) .filter(node => node.classList.contains(CLASS_NAME_ACTIVE)) .forEach(node => node.classList.remove(CLASS_NAME_ACTIVE)) } diff --git a/vendor/twbs/bootstrap/js/src/tab.js b/vendor/twbs/bootstrap/js/src/tab.js index ff12efe2e..139a16cb4 100644 --- a/vendor/twbs/bootstrap/js/src/tab.js +++ b/vendor/twbs/bootstrap/js/src/tab.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): tab.js + * Bootstrap (v5.1.3): tab.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ diff --git a/vendor/twbs/bootstrap/js/src/toast.js b/vendor/twbs/bootstrap/js/src/toast.js index b6c9bdd79..780279be9 100644 --- a/vendor/twbs/bootstrap/js/src/toast.js +++ b/vendor/twbs/bootstrap/js/src/toast.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): toast.js + * Bootstrap (v5.1.3): toast.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -13,6 +13,7 @@ import { import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' import BaseComponent from './base-component' +import { enableDismissTrigger } from './util/component-functions' /** * ------------------------------------------------------------------------ @@ -24,7 +25,6 @@ const NAME = 'toast' const DATA_KEY = 'bs.toast' const EVENT_KEY = `.${DATA_KEY}` -const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY}` const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}` const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}` const EVENT_FOCUSIN = `focusin${EVENT_KEY}` @@ -35,7 +35,7 @@ const EVENT_SHOW = `show${EVENT_KEY}` const EVENT_SHOWN = `shown${EVENT_KEY}` const CLASS_NAME_FADE = 'fade' -const CLASS_NAME_HIDE = 'hide' +const CLASS_NAME_HIDE = 'hide' // @deprecated - kept here only for backwards compatibility const CLASS_NAME_SHOW = 'show' const CLASS_NAME_SHOWING = 'showing' @@ -51,8 +51,6 @@ const Default = { delay: 5000 } -const SELECTOR_DATA_DISMISS = '[data-bs-dismiss="toast"]' - /** * ------------------------------------------------------------------------ * Class Definition @@ -101,15 +99,14 @@ class Toast extends BaseComponent { const complete = () => { this._element.classList.remove(CLASS_NAME_SHOWING) - this._element.classList.add(CLASS_NAME_SHOW) - EventHandler.trigger(this._element, EVENT_SHOWN) this._maybeScheduleHide() } - this._element.classList.remove(CLASS_NAME_HIDE) + this._element.classList.remove(CLASS_NAME_HIDE) // @deprecated reflow(this._element) + this._element.classList.add(CLASS_NAME_SHOW) this._element.classList.add(CLASS_NAME_SHOWING) this._queueCallback(complete, this._element, this._config.animation) @@ -127,11 +124,13 @@ class Toast extends BaseComponent { } const complete = () => { - this._element.classList.add(CLASS_NAME_HIDE) + this._element.classList.add(CLASS_NAME_HIDE) // @deprecated + this._element.classList.remove(CLASS_NAME_SHOWING) + this._element.classList.remove(CLASS_NAME_SHOW) EventHandler.trigger(this._element, EVENT_HIDDEN) } - this._element.classList.remove(CLASS_NAME_SHOW) + this._element.classList.add(CLASS_NAME_SHOWING) this._queueCallback(complete, this._element, this._config.animation) } @@ -201,7 +200,6 @@ class Toast extends BaseComponent { } _setListeners() { - EventHandler.on(this._element, EVENT_CLICK_DISMISS, SELECTOR_DATA_DISMISS, () => this.hide()) EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true)) EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false)) EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true)) @@ -230,6 +228,8 @@ class Toast extends BaseComponent { } } +enableDismissTrigger(Toast) + /** * ------------------------------------------------------------------------ * jQuery diff --git a/vendor/twbs/bootstrap/js/src/tooltip.js b/vendor/twbs/bootstrap/js/src/tooltip.js index cd4a2878e..d8bb31a76 100644 --- a/vendor/twbs/bootstrap/js/src/tooltip.js +++ b/vendor/twbs/bootstrap/js/src/tooltip.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): tooltip.js + * Bootstrap (v5.1.3): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -17,10 +17,7 @@ import { noop, typeCheckConfig } from './util/index' -import { - DefaultAllowlist, - sanitizeHtml -} from './util/sanitizer' +import { DefaultAllowlist, sanitizeHtml } from './util/sanitizer' import Data from './dom/data' import EventHandler from './dom/event-handler' import Manipulator from './dom/manipulator' @@ -37,7 +34,6 @@ const NAME = 'tooltip' const DATA_KEY = 'bs.tooltip' const EVENT_KEY = `.${DATA_KEY}` const CLASS_PREFIX = 'bs-tooltip' -const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g') const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']) const DefaultType = { @@ -112,6 +108,9 @@ const HOVER_STATE_SHOW = 'show' const HOVER_STATE_OUT = 'out' const SELECTOR_TOOLTIP_INNER = '.tooltip-inner' +const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}` + +const EVENT_MODAL_HIDE = 'hide.bs.modal' const TRIGGER_HOVER = 'hover' const TRIGGER_FOCUS = 'focus' @@ -206,16 +205,13 @@ class Tooltip extends BaseComponent { dispose() { clearTimeout(this._timeout) - EventHandler.off(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler) + EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler) if (this.tip) { this.tip.remove() } - if (this._popper) { - this._popper.destroy() - } - + this._disposePopper() super.dispose() } @@ -238,14 +234,20 @@ class Tooltip extends BaseComponent { return } + // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title` + // This will be removed later in favor of a `setContent` method + if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) { + this._disposePopper() + this.tip.remove() + this.tip = null + } + const tip = this.getTipElement() const tipId = getUID(this.constructor.NAME) tip.setAttribute('id', tipId) this._element.setAttribute('aria-describedby', tipId) - this.setContent() - if (this._config.animation) { tip.classList.add(CLASS_NAME_FADE) } @@ -261,7 +263,7 @@ class Tooltip extends BaseComponent { Data.set(tip, this.constructor.DATA_KEY, this) if (!this._element.ownerDocument.documentElement.contains(this.tip)) { - container.appendChild(tip) + container.append(tip) EventHandler.trigger(this._element, this.constructor.Event.INSERTED) } @@ -273,7 +275,7 @@ class Tooltip extends BaseComponent { tip.classList.add(CLASS_NAME_SHOW) - const customClass = typeof this._config.customClass === 'function' ? this._config.customClass() : this._config.customClass + const customClass = this._resolvePossibleFunction(this._config.customClass) if (customClass) { tip.classList.add(...customClass.split(' ')) } @@ -322,10 +324,7 @@ class Tooltip extends BaseComponent { this._element.removeAttribute('aria-describedby') EventHandler.trigger(this._element, this.constructor.Event.HIDDEN) - if (this._popper) { - this._popper.destroy() - this._popper = null - } + this._disposePopper() } const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE) @@ -371,14 +370,28 @@ class Tooltip extends BaseComponent { const element = document.createElement('div') element.innerHTML = this._config.template - this.tip = element.children[0] + const tip = element.children[0] + this.setContent(tip) + tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW) + + this.tip = tip return this.tip } - setContent() { - const tip = this.getTipElement() - this.setElementContent(SelectorEngine.findOne(SELECTOR_TOOLTIP_INNER, tip), this.getTitle()) - tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW) + setContent(tip) { + this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER) + } + + _sanitizeAndSetContent(template, content, selector) { + const templateElement = SelectorEngine.findOne(selector, template) + + if (!content && templateElement) { + templateElement.remove() + return + } + + // we use append for html objects to maintain js events + this.setElementContent(templateElement, content) } setElementContent(element, content) { @@ -393,7 +406,7 @@ class Tooltip extends BaseComponent { if (this._config.html) { if (content.parentNode !== element) { element.innerHTML = '' - element.appendChild(content) + element.append(content) } } else { element.textContent = content.textContent @@ -414,15 +427,9 @@ class Tooltip extends BaseComponent { } getTitle() { - let title = this._element.getAttribute('data-bs-original-title') - - if (!title) { - title = typeof this._config.title === 'function' ? - this._config.title.call(this._element) : - this._config.title - } + const title = this._element.getAttribute('data-bs-original-title') || this._config.title - return title + return this._resolvePossibleFunction(title) } updateAttachment(attachment) { @@ -440,15 +447,7 @@ class Tooltip extends BaseComponent { // Private _initializeOnDelegatedTarget(event, context) { - const dataKey = this.constructor.DATA_KEY - context = context || Data.get(event.delegateTarget, dataKey) - - if (!context) { - context = new this.constructor(event.delegateTarget, this._getDelegateConfig()) - Data.set(event.delegateTarget, dataKey, context) - } - - return context + return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()) } _getOffset() { @@ -465,6 +464,10 @@ class Tooltip extends BaseComponent { return offset } + _resolvePossibleFunction(content) { + return typeof content === 'function' ? content.call(this._element) : content + } + _getPopperConfig(attachment) { const defaultBsPopperConfig = { placement: attachment, @@ -514,7 +517,7 @@ class Tooltip extends BaseComponent { } _addAttachmentClass(attachment) { - this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`) + this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`) } _getAttachment(placement) { @@ -546,7 +549,7 @@ class Tooltip extends BaseComponent { } } - EventHandler.on(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler) + EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler) if (this._config.selector) { this._config = { @@ -686,26 +689,32 @@ class Tooltip extends BaseComponent { _getDelegateConfig() { const config = {} - if (this._config) { - for (const key in this._config) { - if (this.constructor.Default[key] !== this._config[key]) { - config[key] = this._config[key] - } + for (const key in this._config) { + if (this.constructor.Default[key] !== this._config[key]) { + config[key] = this._config[key] } } + // In the future can be replaced with: + // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]]) + // `Object.fromEntries(keysWithDifferentValues)` return config } _cleanTipClass() { const tip = this.getTipElement() - const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX) + const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g') + const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex) if (tabClass !== null && tabClass.length > 0) { tabClass.map(token => token.trim()) .forEach(tClass => tip.classList.remove(tClass)) } } + _getBasicClassPrefix() { + return CLASS_PREFIX + } + _handlePopperPlacementChange(popperData) { const { state } = popperData @@ -718,6 +727,13 @@ class Tooltip extends BaseComponent { this._addAttachmentClass(this._getAttachment(state.placement)) } + _disposePopper() { + if (this._popper) { + this._popper.destroy() + this._popper = null + } + } + // Static static jQueryInterface(config) { diff --git a/vendor/twbs/bootstrap/js/src/util/backdrop.js b/vendor/twbs/bootstrap/js/src/util/backdrop.js index 7ba7b4c43..04c763518 100644 --- a/vendor/twbs/bootstrap/js/src/util/backdrop.js +++ b/vendor/twbs/bootstrap/js/src/util/backdrop.js @@ -1,7 +1,7 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): util/backdrop.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Bootstrap (v5.1.3): util/backdrop.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -9,6 +9,7 @@ import EventHandler from '../dom/event-handler' import { execute, executeAfterTransition, getElement, reflow, typeCheckConfig } from './index' const Default = { + className: 'modal-backdrop', isVisible: true, // if false, we use the backdrop helper without adding any element to the dom isAnimated: false, rootElement: 'body', // give the choice to place backdrop under different elements @@ -16,13 +17,13 @@ const Default = { } const DefaultType = { + className: 'string', isVisible: 'boolean', isAnimated: 'boolean', rootElement: '(element|string)', clickCallback: '(function|null)' } const NAME = 'backdrop' -const CLASS_NAME_BACKDROP = 'modal-backdrop' const CLASS_NAME_FADE = 'fade' const CLASS_NAME_SHOW = 'show' @@ -73,7 +74,7 @@ class Backdrop { _getElement() { if (!this._element) { const backdrop = document.createElement('div') - backdrop.className = CLASS_NAME_BACKDROP + backdrop.className = this._config.className if (this._config.isAnimated) { backdrop.classList.add(CLASS_NAME_FADE) } @@ -101,7 +102,7 @@ class Backdrop { return } - this._config.rootElement.appendChild(this._getElement()) + this._config.rootElement.append(this._getElement()) EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => { execute(this._config.clickCallback) diff --git a/vendor/twbs/bootstrap/js/src/util/component-functions.js b/vendor/twbs/bootstrap/js/src/util/component-functions.js new file mode 100644 index 000000000..bd44c3fdc --- /dev/null +++ b/vendor/twbs/bootstrap/js/src/util/component-functions.js @@ -0,0 +1,34 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.3): util/component-functions.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + +import EventHandler from '../dom/event-handler' +import { getElementFromSelector, isDisabled } from './index' + +const enableDismissTrigger = (component, method = 'hide') => { + const clickEvent = `click.dismiss${component.EVENT_KEY}` + const name = component.NAME + + EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { + if (['A', 'AREA'].includes(this.tagName)) { + event.preventDefault() + } + + if (isDisabled(this)) { + return + } + + const target = getElementFromSelector(this) || this.closest(`.${name}`) + const instance = component.getOrCreateInstance(target) + + // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method + instance[method]() + }) +} + +export { + enableDismissTrigger +} diff --git a/vendor/twbs/bootstrap/js/src/util/focustrap.js b/vendor/twbs/bootstrap/js/src/util/focustrap.js new file mode 100644 index 000000000..44d5f47eb --- /dev/null +++ b/vendor/twbs/bootstrap/js/src/util/focustrap.js @@ -0,0 +1,105 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.3): util/focustrap.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + +import EventHandler from '../dom/event-handler' +import SelectorEngine from '../dom/selector-engine' +import { typeCheckConfig } from './index' + +const Default = { + trapElement: null, // The element to trap focus inside of + autofocus: true +} + +const DefaultType = { + trapElement: 'element', + autofocus: 'boolean' +} + +const NAME = 'focustrap' +const DATA_KEY = 'bs.focustrap' +const EVENT_KEY = `.${DATA_KEY}` +const EVENT_FOCUSIN = `focusin${EVENT_KEY}` +const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY}` + +const TAB_KEY = 'Tab' +const TAB_NAV_FORWARD = 'forward' +const TAB_NAV_BACKWARD = 'backward' + +class FocusTrap { + constructor(config) { + this._config = this._getConfig(config) + this._isActive = false + this._lastTabNavDirection = null + } + + activate() { + const { trapElement, autofocus } = this._config + + if (this._isActive) { + return + } + + if (autofocus) { + trapElement.focus() + } + + EventHandler.off(document, EVENT_KEY) // guard against infinite focus loop + EventHandler.on(document, EVENT_FOCUSIN, event => this._handleFocusin(event)) + EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)) + + this._isActive = true + } + + deactivate() { + if (!this._isActive) { + return + } + + this._isActive = false + EventHandler.off(document, EVENT_KEY) + } + + // Private + + _handleFocusin(event) { + const { target } = event + const { trapElement } = this._config + + if (target === document || target === trapElement || trapElement.contains(target)) { + return + } + + const elements = SelectorEngine.focusableChildren(trapElement) + + if (elements.length === 0) { + trapElement.focus() + } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { + elements[elements.length - 1].focus() + } else { + elements[0].focus() + } + } + + _handleKeydown(event) { + if (event.key !== TAB_KEY) { + return + } + + this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD + } + + _getConfig(config) { + config = { + ...Default, + ...(typeof config === 'object' ? config : {}) + } + typeCheckConfig(NAME, config, DefaultType) + return config + } +} + +export default FocusTrap diff --git a/vendor/twbs/bootstrap/js/src/util/index.js b/vendor/twbs/bootstrap/js/src/util/index.js index 7c317b016..d05a3cbd7 100644 --- a/vendor/twbs/bootstrap/js/src/util/index.js +++ b/vendor/twbs/bootstrap/js/src/util/index.js @@ -1,8 +1,6 @@ -import SelectorEngine from '../dom/selector-engine' - /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): util/index.js + * Bootstrap (v5.1.3): util/index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ @@ -120,7 +118,7 @@ const getElement = obj => { } if (typeof obj === 'string' && obj.length > 0) { - return SelectorEngine.findOne(obj) + return document.querySelector(obj) } return null @@ -189,7 +187,18 @@ const findShadowRoot = element => { const noop = () => {} -const reflow = element => element.offsetHeight +/** + * Trick to restart an element's animation + * + * @param {HTMLElement} element + * @return void + * + * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation + */ +const reflow = element => { + // eslint-disable-next-line no-unused-expressions + element.offsetHeight +} const getjQuery = () => { const { jQuery } = window diff --git a/vendor/twbs/bootstrap/js/src/util/sanitizer.js b/vendor/twbs/bootstrap/js/src/util/sanitizer.js index 49f66417d..339c916c6 100644 --- a/vendor/twbs/bootstrap/js/src/util/sanitizer.js +++ b/vendor/twbs/bootstrap/js/src/util/sanitizer.js @@ -1,11 +1,11 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): util/sanitizer.js + * Bootstrap (v5.1.3): util/sanitizer.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ -const uriAttrs = new Set([ +const uriAttributes = new Set([ 'background', 'cite', 'href', @@ -21,33 +21,33 @@ const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i /** * A pattern that recognizes a commonly useful subset of URLs that are safe. * - * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts */ -const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i +const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i /** * A pattern that matches safe data URLs. Only matches image, video and audio types. * - * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts */ const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i -const allowedAttribute = (attr, allowedAttributeList) => { - const attrName = attr.nodeName.toLowerCase() +const allowedAttribute = (attribute, allowedAttributeList) => { + const attributeName = attribute.nodeName.toLowerCase() - if (allowedAttributeList.includes(attrName)) { - if (uriAttrs.has(attrName)) { - return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue)) + if (allowedAttributeList.includes(attributeName)) { + if (uriAttributes.has(attributeName)) { + return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)) } return true } - const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp) + const regExp = allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp) // Check if a regular expression validates the attribute. for (let i = 0, len = regExp.length; i < len; i++) { - if (regExp[i].test(attrName)) { + if (regExp[i].test(attributeName)) { return true } } @@ -100,25 +100,24 @@ export function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) { const domParser = new window.DOMParser() const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html') - const allowlistKeys = Object.keys(allowList) const elements = [].concat(...createdDocument.body.querySelectorAll('*')) for (let i = 0, len = elements.length; i < len; i++) { - const el = elements[i] - const elName = el.nodeName.toLowerCase() + const element = elements[i] + const elementName = element.nodeName.toLowerCase() - if (!allowlistKeys.includes(elName)) { - el.remove() + if (!Object.keys(allowList).includes(elementName)) { + element.remove() continue } - const attributeList = [].concat(...el.attributes) - const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []) + const attributeList = [].concat(...element.attributes) + const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []) - attributeList.forEach(attr => { - if (!allowedAttribute(attr, allowedAttributes)) { - el.removeAttribute(attr.nodeName) + attributeList.forEach(attribute => { + if (!allowedAttribute(attribute, allowedAttributes)) { + element.removeAttribute(attribute.nodeName) } }) } diff --git a/vendor/twbs/bootstrap/js/src/util/scrollbar.js b/vendor/twbs/bootstrap/js/src/util/scrollbar.js index fad9766ac..a90f21a79 100644 --- a/vendor/twbs/bootstrap/js/src/util/scrollbar.js +++ b/vendor/twbs/bootstrap/js/src/util/scrollbar.js @@ -1,6 +1,6 @@ /** * -------------------------------------------------------------------------- - * Bootstrap (v5.0.2): util/scrollBar.js + * Bootstrap (v5.1.3): util/scrollBar.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ |