mirror of
https://github.com/twbs/bootstrap.git
synced 2022-11-09 12:25:43 -05:00
initial
This commit is contained in:
parent
c3c6591166
commit
1039830b5b
21 changed files with 357 additions and 496 deletions
|
|
@ -42,8 +42,8 @@ const files = [
|
|||
configPropertyName: 'js_bundle_hash'
|
||||
},
|
||||
{
|
||||
file: 'node_modules/@popperjs/core/dist/umd/popper.min.js',
|
||||
configPropertyName: 'popper_hash'
|
||||
file: 'node_modules/@floating-ui/dom/dist/floating-ui.dom.umd.js',
|
||||
configPropertyName: 'floating_ui_hash'
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const BUNDLE = process.env.BUNDLE === 'true'
|
|||
const ESM = process.env.ESM === 'true'
|
||||
|
||||
let fileDestination = `bootstrap${ESM ? '.esm' : ''}`
|
||||
const external = ['@popperjs/core']
|
||||
const external = ['@floating-ui/dom']
|
||||
const plugins = [
|
||||
babel({
|
||||
// Only transpile our source code
|
||||
|
|
@ -20,14 +20,14 @@ const plugins = [
|
|||
})
|
||||
]
|
||||
const globals = {
|
||||
'@popperjs/core': 'Popper'
|
||||
'@floating-ui/dom': 'floatingUi'
|
||||
}
|
||||
|
||||
if (BUNDLE) {
|
||||
fileDestination += '.bundle'
|
||||
// Remove last entry in external array to bundle Popper
|
||||
external.pop()
|
||||
delete globals['@popperjs/core']
|
||||
delete globals['@floating-ui/dom']
|
||||
plugins.push(
|
||||
replace({
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ params:
|
|||
js_hash: "sha384-ODmDIVzN+pFdexxHEHFBQH3/9/vQ9uori45z4JjnFsRydbmQbmL5t1tQ0culUzyK"
|
||||
js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
|
||||
js_bundle_hash: "sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
|
||||
popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.5/dist/umd/popper.min.js"
|
||||
popper_hash: "sha384-Xe+8cL9oJa6tN/veChSP7q+mnSPaj5Bcu9mPX5F5xIGE0DVittaqT5lorf0EI7Vk"
|
||||
floating_ui: "https://cdn.jsdelivr.net/npm/@floating-ui/dom@0.5.4/dist/floating-ui.dom.umd.min.js"
|
||||
floating_ui_hash: "sha384-Os8n9bzoYJ/ESbGD7cW0VOTLk0hO++SO+Y4swXBE2dHrxiZkjADEr5ZGOcc9CorD"
|
||||
|
||||
anchors:
|
||||
min: 2
|
||||
|
|
|
|||
|
|
@ -5,21 +5,18 @@
|
|||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import * as Popper from '@popperjs/core'
|
||||
import { inline, offset, shift } from '@floating-ui/dom'
|
||||
import {
|
||||
defineJQueryPlugin,
|
||||
getElement,
|
||||
getNextActiveElement,
|
||||
isDisabled,
|
||||
isElement,
|
||||
isRTL,
|
||||
isVisible,
|
||||
noop
|
||||
} from './util/index'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import Manipulator from './dom/manipulator'
|
||||
import SelectorEngine from './dom/selector-engine'
|
||||
import BaseComponent from './base-component'
|
||||
import FloatingUi from './util/floating-ui'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
@ -28,7 +25,6 @@ import BaseComponent from './base-component'
|
|||
const NAME = 'dropdown'
|
||||
const DATA_KEY = 'bs.dropdown'
|
||||
const EVENT_KEY = `.${DATA_KEY}`
|
||||
const DATA_API_KEY = '.data-api'
|
||||
|
||||
const ESCAPE_KEY = 'Escape'
|
||||
const TAB_KEY = 'Tab'
|
||||
|
|
@ -40,9 +36,9 @@ 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_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}`
|
||||
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}`
|
||||
const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY}`
|
||||
const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY}`
|
||||
|
||||
const CLASS_NAME_SHOW = 'show'
|
||||
const CLASS_NAME_DROPUP = 'dropup'
|
||||
|
|
@ -58,30 +54,28 @@ const SELECTOR_NAVBAR = '.navbar'
|
|||
const SELECTOR_NAVBAR_NAV = '.navbar-nav'
|
||||
const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'
|
||||
|
||||
const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'
|
||||
const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'
|
||||
const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'
|
||||
const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'
|
||||
const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'
|
||||
const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'
|
||||
const PLACEMENT_TOPCENTER = 'top'
|
||||
const PLACEMENT_TOPEND = 'top-end'
|
||||
const PLACEMENT_TOP = 'top-start'
|
||||
const PLACEMENT_BOTTOMCENTER = 'bottom'
|
||||
const PLACEMENT_BOTTOMEND = 'bottom-end'
|
||||
const PLACEMENT_BOTTOM = 'bottom-start'
|
||||
const PLACEMENT_RIGHT = 'right-start'
|
||||
const PLACEMENT_LEFT = 'left-start'
|
||||
|
||||
const Default = {
|
||||
autoClose: true,
|
||||
boundary: 'clippingParents',
|
||||
display: 'dynamic',
|
||||
offset: [0, 2],
|
||||
popperConfig: null,
|
||||
offset: 10,
|
||||
positionConfig: null,
|
||||
reference: 'toggle'
|
||||
}
|
||||
|
||||
const DefaultType = {
|
||||
autoClose: '(boolean|string)',
|
||||
boundary: '(string|element)',
|
||||
display: 'string',
|
||||
offset: '(array|string|function)',
|
||||
popperConfig: '(null|object|function)',
|
||||
offset: '(number|array|string|function)',
|
||||
positionConfig: '(null|object|function)',
|
||||
reference: '(string|element|object)'
|
||||
}
|
||||
|
||||
|
|
@ -93,10 +87,9 @@ class Dropdown extends BaseComponent {
|
|||
constructor(element, config) {
|
||||
super(element, config)
|
||||
|
||||
this._popper = null
|
||||
this._parent = this._element.parentNode // dropdown wrapper
|
||||
this._menu = SelectorEngine.findOne(SELECTOR_MENU, this._parent)
|
||||
this._inNavbar = this._detectNavbar()
|
||||
this._positionHelper = new FloatingUi(this._element)
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
|
@ -132,7 +125,7 @@ class Dropdown extends BaseComponent {
|
|||
return
|
||||
}
|
||||
|
||||
this._createPopper()
|
||||
this.update()
|
||||
|
||||
// If this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
|
|
@ -164,19 +157,9 @@ class Dropdown extends BaseComponent {
|
|||
this._completeHide(relatedTarget)
|
||||
}
|
||||
|
||||
dispose() {
|
||||
if (this._popper) {
|
||||
this._popper.destroy()
|
||||
}
|
||||
|
||||
super.dispose()
|
||||
}
|
||||
|
||||
update() {
|
||||
this._inNavbar = this._detectNavbar()
|
||||
if (this._popper) {
|
||||
this._popper.update()
|
||||
}
|
||||
const reference = this._positionHelper.getReferenceElement(this._config.reference, this._parent, NAME)
|
||||
this._positionHelper.calculate(reference, this._menu, this._getFloatingUiConfig())
|
||||
}
|
||||
|
||||
// Private
|
||||
|
|
@ -194,47 +177,28 @@ class Dropdown extends BaseComponent {
|
|||
}
|
||||
}
|
||||
|
||||
if (this._popper) {
|
||||
this._popper.destroy()
|
||||
}
|
||||
|
||||
this._menu.classList.remove(CLASS_NAME_SHOW)
|
||||
this._element.classList.remove(CLASS_NAME_SHOW)
|
||||
this._element.setAttribute('aria-expanded', 'false')
|
||||
Manipulator.removeDataAttribute(this._menu, 'popper')
|
||||
this._positionHelper.stop()
|
||||
EventHandler.trigger(this._element, EVENT_HIDDEN, relatedTarget)
|
||||
}
|
||||
|
||||
_getConfig(config) {
|
||||
config = super._getConfig(config)
|
||||
|
||||
if (typeof config.reference === 'object' && !isElement(config.reference) &&
|
||||
typeof config.reference.getBoundingClientRect !== 'function'
|
||||
) {
|
||||
// Popper virtual elements require a getBoundingClientRect method
|
||||
throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
|
||||
_getFloatingUiConfig() {
|
||||
const defaultBsConfig = {
|
||||
placement: this._getPlacement(),
|
||||
middleware: [offset(this._positionHelper.parseOffset(this._config.offset)), shift()]
|
||||
}
|
||||
|
||||
return config
|
||||
// Disable Popper if we have a static display or Dropdown is in Navbar
|
||||
if (this._detectNavbar() || this._config.display === 'static') {
|
||||
defaultBsConfig.middleware.push(inline())
|
||||
}
|
||||
|
||||
_createPopper() {
|
||||
if (typeof Popper === 'undefined') {
|
||||
throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)')
|
||||
return {
|
||||
...defaultBsConfig,
|
||||
...(typeof this._config.positionConfig === 'function' ? this._config.positionConfig(defaultBsConfig) : this._config.positionConfig)
|
||||
}
|
||||
|
||||
let referenceElement = this._element
|
||||
|
||||
if (this._config.reference === 'parent') {
|
||||
referenceElement = this._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()
|
||||
this._popper = Popper.createPopper(referenceElement, this._menu, popperConfig)
|
||||
}
|
||||
|
||||
_isShown() {
|
||||
|
|
@ -244,20 +208,15 @@ class Dropdown extends BaseComponent {
|
|||
_getPlacement() {
|
||||
const parentDropdown = this._parent
|
||||
|
||||
if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
|
||||
return PLACEMENT_RIGHT
|
||||
const matches = {
|
||||
[CLASS_NAME_DROPEND]: PLACEMENT_RIGHT,
|
||||
[CLASS_NAME_DROPSTART]: PLACEMENT_LEFT,
|
||||
[CLASS_NAME_DROPUP_CENTER]: PLACEMENT_TOPCENTER,
|
||||
[CLASS_NAME_DROPDOWN_CENTER]: PLACEMENT_BOTTOMCENTER
|
||||
}
|
||||
|
||||
if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
|
||||
return PLACEMENT_LEFT
|
||||
}
|
||||
|
||||
if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
|
||||
return PLACEMENT_TOPCENTER
|
||||
}
|
||||
|
||||
if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
|
||||
return PLACEMENT_BOTTOMCENTER
|
||||
const match = Object.keys(matches).find(keyClass => parentDropdown.classList.contains(keyClass))
|
||||
if (match) {
|
||||
return matches[match]
|
||||
}
|
||||
|
||||
// We need to trim the value because custom properties can also include spaces
|
||||
|
|
@ -274,52 +233,6 @@ class Dropdown extends BaseComponent {
|
|||
return this._element.closest(SELECTOR_NAVBAR) !== null
|
||||
}
|
||||
|
||||
_getOffset() {
|
||||
const { offset } = this._config
|
||||
|
||||
if (typeof offset === 'string') {
|
||||
return offset.split(',').map(value => Number.parseInt(value, 10))
|
||||
}
|
||||
|
||||
if (typeof offset === 'function') {
|
||||
return popperData => offset(popperData, this._element)
|
||||
}
|
||||
|
||||
return offset
|
||||
}
|
||||
|
||||
_getPopperConfig() {
|
||||
const defaultBsPopperConfig = {
|
||||
placement: this._getPlacement(),
|
||||
modifiers: [{
|
||||
name: 'preventOverflow',
|
||||
options: {
|
||||
boundary: this._config.boundary
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: this._getOffset()
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
// Disable Popper if we have a static display or Dropdown is in Navbar
|
||||
if (this._inNavbar || this._config.display === 'static') {
|
||||
Manipulator.setDataAttribute(this._menu, 'popper', 'static') // todo:v6 remove
|
||||
defaultBsPopperConfig.modifiers = [{
|
||||
name: 'applyStyles',
|
||||
enabled: false
|
||||
}]
|
||||
}
|
||||
|
||||
return {
|
||||
...defaultBsPopperConfig,
|
||||
...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
|
||||
}
|
||||
}
|
||||
|
||||
_selectMenuItem({ key, target }) {
|
||||
const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element))
|
||||
|
||||
|
|
@ -364,11 +277,7 @@ class Dropdown extends BaseComponent {
|
|||
|
||||
const composedPath = event.composedPath()
|
||||
const isMenuTarget = composedPath.includes(context._menu)
|
||||
if (
|
||||
composedPath.includes(context._element) ||
|
||||
(context._config.autoClose === 'inside' && !isMenuTarget) ||
|
||||
(context._config.autoClose === 'outside' && isMenuTarget)
|
||||
) {
|
||||
if (composedPath.includes(context._element) || (context._config.autoClose === 'inside' && !isMenuTarget) || (context._config.autoClose === 'outside' && isMenuTarget)) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@ const Default = {
|
|||
offset: [0, 8],
|
||||
placement: 'right',
|
||||
template: '<div class="popover" role="tooltip">' +
|
||||
'<div class="popover-arrow"></div>' +
|
||||
'<div class="popover-inner">' +
|
||||
'<h3 class="popover-header"></h3>' +
|
||||
'<div class="popover-body"></div>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
trigger: 'click'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import * as Popper from '@popperjs/core'
|
||||
import { defineJQueryPlugin, findShadowRoot, getElement, getUID, isRTL, noop } from './util/index'
|
||||
import { defineJQueryPlugin, findShadowRoot, getElement, getUID, isVisible, noop } from './util/index'
|
||||
import { DefaultAllowlist } from './util/sanitizer'
|
||||
import EventHandler from './dom/event-handler'
|
||||
import Manipulator from './dom/manipulator'
|
||||
import BaseComponent from './base-component'
|
||||
import TemplateFactory from './util/template-factory'
|
||||
import FloatingUi from './util/floating-ui'
|
||||
import { flip, hide, offset, shift } from '@floating-ui/dom'
|
||||
|
||||
/**
|
||||
* Constants
|
||||
|
|
@ -48,9 +49,9 @@ const EVENT_MOUSELEAVE = 'mouseleave'
|
|||
const AttachmentMap = {
|
||||
AUTO: 'auto',
|
||||
TOP: 'top',
|
||||
RIGHT: isRTL() ? 'left' : 'right',
|
||||
RIGHT: 'right',
|
||||
BOTTOM: 'bottom',
|
||||
LEFT: isRTL() ? 'right' : 'left'
|
||||
LEFT: 'left'
|
||||
}
|
||||
|
||||
const Default = {
|
||||
|
|
@ -62,14 +63,13 @@ const Default = {
|
|||
delay: 0,
|
||||
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
|
||||
html: false,
|
||||
offset: [0, 0],
|
||||
offset: 0,
|
||||
placement: 'top',
|
||||
popperConfig: null,
|
||||
positionConfig: null,
|
||||
sanitize: true,
|
||||
sanitizeFn: null,
|
||||
selector: false,
|
||||
template: '<div class="tooltip" role="tooltip">' +
|
||||
'<div class="tooltip-arrow"></div>' +
|
||||
'<div class="tooltip-inner"></div>' +
|
||||
'</div>',
|
||||
title: '',
|
||||
|
|
@ -85,9 +85,9 @@ const DefaultType = {
|
|||
delay: '(number|object)',
|
||||
fallbackPlacements: 'array',
|
||||
html: 'boolean',
|
||||
offset: '(array|string|function)',
|
||||
offset: '(number|array|string|function)',
|
||||
placement: '(string|function)',
|
||||
popperConfig: '(null|object|function)',
|
||||
positionConfig: '(null|object|function)',
|
||||
sanitize: 'boolean',
|
||||
sanitizeFn: '(null|function)',
|
||||
selector: '(string|boolean)',
|
||||
|
|
@ -102,10 +102,6 @@ const DefaultType = {
|
|||
|
||||
class Tooltip extends BaseComponent {
|
||||
constructor(element, config) {
|
||||
if (typeof Popper === 'undefined') {
|
||||
throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)')
|
||||
}
|
||||
|
||||
super(element, config)
|
||||
|
||||
// Private
|
||||
|
|
@ -113,7 +109,7 @@ class Tooltip extends BaseComponent {
|
|||
this._timeout = 0
|
||||
this._isHovered = false
|
||||
this._activeTrigger = {}
|
||||
this._popper = null
|
||||
this._positionHelper = new FloatingUi(this._element)
|
||||
this._templateFactory = null
|
||||
this._newContent = null
|
||||
|
||||
|
|
@ -194,7 +190,7 @@ class Tooltip extends BaseComponent {
|
|||
}
|
||||
|
||||
show() {
|
||||
if (this._element.style.display === 'none') {
|
||||
if (!isVisible(this._element)) {
|
||||
throw new Error('Please use show on visible elements')
|
||||
}
|
||||
|
||||
|
|
@ -216,24 +212,9 @@ class Tooltip extends BaseComponent {
|
|||
this.tip = null
|
||||
}
|
||||
|
||||
const tip = this._getTipElement()
|
||||
this.update()
|
||||
|
||||
this._element.setAttribute('aria-describedby', tip.getAttribute('id'))
|
||||
|
||||
const { container } = this._config
|
||||
|
||||
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
|
||||
container.append(tip)
|
||||
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED))
|
||||
}
|
||||
|
||||
if (this._popper) {
|
||||
this._popper.update()
|
||||
} else {
|
||||
this._popper = this._createPopper(tip)
|
||||
}
|
||||
|
||||
tip.classList.add(CLASS_NAME_SHOW)
|
||||
this.tip.classList.add(CLASS_NAME_SHOW)
|
||||
|
||||
// If this is a touch-enabled device we add extra
|
||||
// empty mouseover listeners to the body's immediate children;
|
||||
|
|
@ -291,24 +272,17 @@ class Tooltip extends BaseComponent {
|
|||
}
|
||||
|
||||
if (!this._isHovered) {
|
||||
this._positionHelper.stop()
|
||||
tip.remove()
|
||||
}
|
||||
|
||||
this._element.removeAttribute('aria-describedby')
|
||||
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN))
|
||||
|
||||
this._disposePopper()
|
||||
}
|
||||
|
||||
this._queueCallback(complete, this.tip, this._isAnimated())
|
||||
}
|
||||
|
||||
update() {
|
||||
if (this._popper) {
|
||||
this._popper.update()
|
||||
}
|
||||
}
|
||||
|
||||
// Protected
|
||||
_isWithContent() {
|
||||
return Boolean(this._getTitle())
|
||||
|
|
@ -317,6 +291,14 @@ class Tooltip extends BaseComponent {
|
|||
_getTipElement() {
|
||||
if (!this.tip) {
|
||||
this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())
|
||||
this._element.setAttribute('aria-describedby', this.tip.getAttribute('id'))
|
||||
}
|
||||
|
||||
const { container } = this._config
|
||||
|
||||
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
|
||||
container.append(this.tip)
|
||||
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED))
|
||||
}
|
||||
|
||||
return this.tip
|
||||
|
|
@ -331,8 +313,6 @@ class Tooltip extends BaseComponent {
|
|||
}
|
||||
|
||||
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW)
|
||||
// todo: on v6 the following can be achieved with CSS only
|
||||
tip.classList.add(`bs-${this.constructor.NAME}-auto`)
|
||||
|
||||
const tipId = getUID(this.constructor.NAME).toString()
|
||||
|
||||
|
|
@ -392,79 +372,39 @@ class Tooltip extends BaseComponent {
|
|||
return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW)
|
||||
}
|
||||
|
||||
_createPopper(tip) {
|
||||
const placement = typeof this._config.placement === 'function' ?
|
||||
this._config.placement.call(this, tip, this._element) :
|
||||
this._config.placement
|
||||
const attachment = AttachmentMap[placement.toUpperCase()]
|
||||
return Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
|
||||
update() {
|
||||
this._positionHelper.calculate(this._element, this._getTipElement(), this._getFloatingUiConfig(), { position: 'fixed' })
|
||||
}
|
||||
|
||||
_getOffset() {
|
||||
const { offset } = this._config
|
||||
|
||||
if (typeof offset === 'string') {
|
||||
return offset.split(',').map(value => Number.parseInt(value, 10))
|
||||
}
|
||||
|
||||
if (typeof offset === 'function') {
|
||||
return popperData => offset(popperData, this._element)
|
||||
}
|
||||
|
||||
return offset
|
||||
}
|
||||
|
||||
_resolvePossibleFunction(arg) {
|
||||
return typeof arg === 'function' ? arg.call(this._element) : arg
|
||||
}
|
||||
|
||||
_getPopperConfig(attachment) {
|
||||
const defaultBsPopperConfig = {
|
||||
placement: attachment,
|
||||
modifiers: [
|
||||
{
|
||||
name: 'flip',
|
||||
options: {
|
||||
fallbackPlacements: this._config.fallbackPlacements
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: this._getOffset()
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'preventOverflow',
|
||||
options: {
|
||||
boundary: this._config.boundary
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'arrow',
|
||||
options: {
|
||||
element: `.${this.constructor.NAME}-arrow`
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'preSetPlacement',
|
||||
enabled: true,
|
||||
phase: 'beforeMain',
|
||||
fn: data => {
|
||||
// Pre-set Popper's placement attribute in order to read the arrow sizes properly.
|
||||
// Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
|
||||
this._getTipElement().setAttribute('data-popper-placement', data.state.placement)
|
||||
}
|
||||
}
|
||||
_getFloatingUiConfig() {
|
||||
const defaultBsConfig = {
|
||||
strategy: 'fixed',
|
||||
placement: this._getPlacement(),
|
||||
middleware: [
|
||||
offset(this._positionHelper.parseOffset(this._config.offset)),
|
||||
flip({ fallbackPlacements: this._config.fallbackPlacements }),
|
||||
shift(),
|
||||
hide()
|
||||
]
|
||||
}
|
||||
|
||||
return {
|
||||
...defaultBsPopperConfig,
|
||||
...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
|
||||
...defaultBsConfig,
|
||||
...(typeof this._config.positionConfig === 'function' ? this._config.positionConfig(defaultBsConfig) : this._config.positionConfig)
|
||||
}
|
||||
}
|
||||
|
||||
_getPlacement() {
|
||||
const placement = typeof this._config.placement === 'function' ?
|
||||
this._config.placement.call(this, this.tip, this._element) :
|
||||
this._config.placement
|
||||
return AttachmentMap[placement.toUpperCase()]
|
||||
}
|
||||
|
||||
_resolvePossibleFunction(arg) {
|
||||
return typeof arg === 'function' ? arg.call(this._element) : arg
|
||||
}
|
||||
|
||||
_setListeners() {
|
||||
const triggers = this._config.trigger.split(' ')
|
||||
|
||||
|
|
@ -621,13 +561,6 @@ class Tooltip extends BaseComponent {
|
|||
return config
|
||||
}
|
||||
|
||||
_disposePopper() {
|
||||
if (this._popper) {
|
||||
this._popper.destroy()
|
||||
this._popper = null
|
||||
}
|
||||
}
|
||||
|
||||
// Static
|
||||
static jQueryInterface(config) {
|
||||
return this.each(function () {
|
||||
|
|
|
|||
92
js/src/util/floating-ui.js
Normal file
92
js/src/util/floating-ui.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// import {computePosition, flip, shift} from '@floating-ui/dom'
|
||||
//
|
||||
//
|
||||
import { autoUpdate, computePosition } from '@floating-ui/dom'
|
||||
import { getElement, isElement } from './index'
|
||||
import Manipulator from '../dom/manipulator'
|
||||
|
||||
class FloatingUi {
|
||||
constructor(element) {
|
||||
if (typeof computePosition === 'undefined') {
|
||||
throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)')
|
||||
}
|
||||
|
||||
this._element = element
|
||||
this._cleanup = null
|
||||
}
|
||||
|
||||
calculate(reference, floatingEl, config, extraCss = {}) {
|
||||
this._cleanup = autoUpdate(reference, floatingEl, () => {
|
||||
computePosition(reference, floatingEl, config)
|
||||
.then(({ x, y, placement, middlewareData }) => {
|
||||
const positionCss = {
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
}
|
||||
console.log(middlewareData) // eslint-disable-line no-console
|
||||
if (middlewareData.hide) {
|
||||
const { referenceHidden } = middlewareData.hide
|
||||
|
||||
Object.assign(floatingEl.style, {
|
||||
visibility: referenceHidden ? 'hidden' : 'visible'
|
||||
})
|
||||
}
|
||||
|
||||
Object.assign(floatingEl.style, { ...positionCss, ...extraCss })
|
||||
Manipulator.setDataAttribute(floatingEl, 'placement', placement)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this._cleanup) {
|
||||
this._cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
getReferenceElement(reference, parent, PluginName) {
|
||||
if (reference === 'parent') {
|
||||
return parent
|
||||
}
|
||||
|
||||
if (isElement(reference)) {
|
||||
return getElement(reference)
|
||||
}
|
||||
|
||||
if (typeof reference === 'object') {
|
||||
if (typeof reference.getBoundingClientRect !== 'function') {
|
||||
throw new TypeError(`${PluginName.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`)
|
||||
}
|
||||
|
||||
return reference
|
||||
}
|
||||
|
||||
return this._element
|
||||
}
|
||||
|
||||
parseOffset(value) {
|
||||
console.log(value) // eslint-disable-line no-console
|
||||
if (typeof value === 'function') {
|
||||
return popperData => value(popperData, this._element)
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
console.log('offset', value) // eslint-disable-line no-console
|
||||
value = [
|
||||
Number.parseInt(value.split(',')[0], 10),
|
||||
Number.parseInt(value.split(',')[1] || 0, 10)
|
||||
]
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return {
|
||||
mainAxis: value[0],
|
||||
alignmentAxis: value[1]
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
export default FloatingUi
|
||||
29
package-lock.json
generated
29
package-lock.json
generated
|
|
@ -18,6 +18,9 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^0.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.18.10",
|
||||
"@babel/core": "^7.18.10",
|
||||
|
|
@ -1770,6 +1773,19 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz",
|
||||
"integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg=="
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.4.tgz",
|
||||
"integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
|
||||
|
|
@ -11705,6 +11721,19 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@floating-ui/core": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz",
|
||||
"integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg=="
|
||||
},
|
||||
"@floating-ui/dom": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.4.tgz",
|
||||
"integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==",
|
||||
"requires": {
|
||||
"@floating-ui/core": "^0.7.3"
|
||||
}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
|
||||
|
|
|
|||
|
|
@ -101,13 +101,13 @@
|
|||
"watch-js-docs": "nodemon --watch site/assets/js/ --ext js --exec \"npm run js-lint\""
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.11.5"
|
||||
"@floating-ui/dom": "^0.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.18.10",
|
||||
"@babel/core": "^7.18.10",
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"@floating-ui/dom": "^0.5.4",
|
||||
"@rollup/plugin-babel": "^5.3.1",
|
||||
"@rollup/plugin-commonjs": "^22.0.1",
|
||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
||||
|
|
@ -174,7 +174,7 @@
|
|||
},
|
||||
"dependencies": {},
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.11.5"
|
||||
"@floating-ui/dom": "^0.5.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,12 +61,6 @@
|
|||
@include border-radius(var(--#{$prefix}dropdown-border-radius));
|
||||
@include box-shadow(var(--#{$prefix}dropdown-box-shadow));
|
||||
|
||||
&[data-bs-popper] {
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin-top: var(--#{$prefix}dropdown-spacer);
|
||||
}
|
||||
|
||||
@if $dropdown-padding-y == 0 {
|
||||
> .dropdown-item:first-child,
|
||||
> li:first-child .dropdown-item {
|
||||
|
|
@ -82,7 +76,7 @@
|
|||
|
||||
// scss-docs-start responsive-breakpoints
|
||||
// We deliberately hardcode the `bs-` prefix because we check
|
||||
// this custom property in JS to determine Popper's positioning
|
||||
// this custom property in JS to determine positioning
|
||||
|
||||
@each $breakpoint in map-keys($grid-breakpoints) {
|
||||
@include media-breakpoint-up($breakpoint) {
|
||||
|
|
@ -90,20 +84,10 @@
|
|||
|
||||
.dropdown-menu#{$infix}-start {
|
||||
--bs-position: start;
|
||||
|
||||
&[data-bs-popper] {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu#{$infix}-end {
|
||||
--bs-position: end;
|
||||
|
||||
&[data-bs-popper] {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -112,26 +96,12 @@
|
|||
// Allow for dropdowns to go bottom up (aka, dropup-menu)
|
||||
// Just add .dropup after the standard .dropdown class and you're set.
|
||||
.dropup {
|
||||
.dropdown-menu[data-bs-popper] {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: var(--#{$prefix}dropdown-spacer);
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
@include caret(up);
|
||||
}
|
||||
}
|
||||
|
||||
.dropend {
|
||||
.dropdown-menu[data-bs-popper] {
|
||||
top: 0;
|
||||
right: auto;
|
||||
left: 100%;
|
||||
margin-top: 0;
|
||||
margin-left: var(--#{$prefix}dropdown-spacer);
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
@include caret(end);
|
||||
|
|
@ -142,14 +112,6 @@
|
|||
}
|
||||
|
||||
.dropstart {
|
||||
.dropdown-menu[data-bs-popper] {
|
||||
top: 0;
|
||||
right: 100%;
|
||||
left: auto;
|
||||
margin-top: 0;
|
||||
margin-right: var(--#{$prefix}dropdown-spacer);
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
@include caret(start);
|
||||
&::before {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
--#{$prefix}popover-arrow-border: var(--#{$prefix}popover-border-color);
|
||||
// scss-docs-end popover-css-vars
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: var(--#{$prefix}popover-zindex);
|
||||
display: block;
|
||||
max-width: var(--#{$prefix}popover-max-width);
|
||||
|
|
@ -31,16 +34,6 @@
|
|||
@include font-size(var(--#{$prefix}popover-font-size));
|
||||
// Allow breaking very long words so they don't overflow the popover's bounds
|
||||
word-wrap: break-word;
|
||||
background-color: var(--#{$prefix}popover-bg);
|
||||
background-clip: padding-box;
|
||||
border: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
|
||||
@include border-radius(var(--#{$prefix}popover-border-radius));
|
||||
@include box-shadow(var(--#{$prefix}popover-box-shadow));
|
||||
|
||||
.popover-arrow {
|
||||
display: block;
|
||||
width: var(--#{$prefix}popover-arrow-width);
|
||||
height: var(--#{$prefix}popover-arrow-height);
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
|
|
@ -50,16 +43,23 @@
|
|||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.bs-popover-top {
|
||||
> .popover-arrow {
|
||||
bottom: calc((var(--#{$prefix}popover-arrow-height) * -1) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
|
||||
.popover-inner {
|
||||
margin: var(--#{$prefix}popover-arrow-height);
|
||||
background-color: var(--#{$prefix}popover-bg);
|
||||
background-clip: padding-box;
|
||||
border: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-border-color);
|
||||
@include border-radius(var(--#{$prefix}popover-border-radius));
|
||||
@include box-shadow(var(--#{$prefix}popover-box-shadow));
|
||||
}
|
||||
|
||||
.popover[data-bs-placement="top"] {
|
||||
&::before,
|
||||
&::after {
|
||||
left: 50%;
|
||||
border-width: var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
|
||||
}
|
||||
|
||||
|
|
@ -72,41 +72,12 @@
|
|||
bottom: var(--#{$prefix}popover-border-width);
|
||||
border-top-color: var(--#{$prefix}popover-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:begin:ignore */
|
||||
.bs-popover-end {
|
||||
> .popover-arrow {
|
||||
left: calc((var(--#{$prefix}popover-arrow-height) * -1) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
|
||||
width: var(--#{$prefix}popover-arrow-height);
|
||||
height: var(--#{$prefix}popover-arrow-width);
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
border-right-color: var(--#{$prefix}popover-arrow-border);
|
||||
}
|
||||
|
||||
&::after {
|
||||
left: var(--#{$prefix}popover-border-width);
|
||||
border-right-color: var(--#{$prefix}popover-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:end:ignore */
|
||||
|
||||
.bs-popover-bottom {
|
||||
> .popover-arrow {
|
||||
top: calc((var(--#{$prefix}popover-arrow-height) * -1) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
|
||||
|
||||
.popover[data-bs-placement="bottom"] {
|
||||
&::before,
|
||||
&::after {
|
||||
left: 50%;
|
||||
border-width: 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
|
||||
}
|
||||
|
||||
|
|
@ -119,31 +90,37 @@
|
|||
top: var(--#{$prefix}popover-border-width);
|
||||
border-bottom-color: var(--#{$prefix}popover-bg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* rtl:begin:ignore */
|
||||
|
||||
.popover[data-bs-placement="right"] {
|
||||
&::before,
|
||||
&::after {
|
||||
top: 50%;
|
||||
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height) calc(var(--#{$prefix}popover-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
// This will remove the popover-header's border just below the arrow
|
||||
.popover-header::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
display: block;
|
||||
width: var(--#{$prefix}popover-arrow-width);
|
||||
margin-left: calc(var(--#{$prefix}popover-arrow-width) * -.5); // stylelint-disable-line function-disallowed-list
|
||||
content: "";
|
||||
border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-header-bg);
|
||||
&::before {
|
||||
left: 0;
|
||||
border-right-color: var(--#{$prefix}popover-arrow-border);
|
||||
}
|
||||
|
||||
&::after {
|
||||
left: var(--#{$prefix}popover-border-width);
|
||||
border-right-color: var(--#{$prefix}popover-bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:begin:ignore */
|
||||
.bs-popover-start {
|
||||
> .popover-arrow {
|
||||
right: calc((var(--#{$prefix}popover-arrow-height) * -1) - var(--#{$prefix}popover-border-width)); // stylelint-disable-line function-disallowed-list
|
||||
width: var(--#{$prefix}popover-arrow-height);
|
||||
height: var(--#{$prefix}popover-arrow-width);
|
||||
|
||||
.popover[data-bs-placement="left"] {
|
||||
&::before,
|
||||
&::after {
|
||||
top: 50%;
|
||||
border-width: calc(var(--#{$prefix}popover-arrow-width) * .5) 0 calc(var(--#{$prefix}popover-arrow-width) * .5) var(--#{$prefix}popover-arrow-height); // stylelint-disable-line function-disallowed-list
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&::before {
|
||||
|
|
@ -155,26 +132,24 @@
|
|||
right: var(--#{$prefix}popover-border-width);
|
||||
border-left-color: var(--#{$prefix}popover-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* rtl:end:ignore */
|
||||
|
||||
.bs-popover-auto {
|
||||
&[data-popper-placement^="top"] {
|
||||
@extend .bs-popover-top;
|
||||
}
|
||||
&[data-popper-placement^="right"] {
|
||||
@extend .bs-popover-end;
|
||||
}
|
||||
&[data-popper-placement^="bottom"] {
|
||||
@extend .bs-popover-bottom;
|
||||
}
|
||||
&[data-popper-placement^="left"] {
|
||||
@extend .bs-popover-start;
|
||||
}
|
||||
// This will remove the popover-header's border just below the arrow
|
||||
.popover-header::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
display: block;
|
||||
width: var(--#{$prefix}popover-arrow-width);
|
||||
margin-left: calc(var(--#{$prefix}popover-arrow-width) * -.5); // stylelint-disable-line function-disallowed-list
|
||||
content: "";
|
||||
border-bottom: var(--#{$prefix}popover-border-width) solid var(--#{$prefix}popover-header-bg);
|
||||
}
|
||||
|
||||
|
||||
// Offset the popover to account for the popover arrow
|
||||
.popover-header {
|
||||
padding: var(--#{$prefix}popover-header-padding-y) var(--#{$prefix}popover-header-padding-x);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
--#{$prefix}tooltip-max-width: #{$tooltip-max-width};
|
||||
--#{$prefix}tooltip-padding-x: #{$tooltip-padding-x};
|
||||
--#{$prefix}tooltip-padding-y: #{$tooltip-padding-y};
|
||||
--#{$prefix}tooltip-margin: #{$tooltip-margin};
|
||||
@include rfs($tooltip-font-size, --#{$prefix}tooltip-font-size);
|
||||
--#{$prefix}tooltip-color: #{$tooltip-color};
|
||||
--#{$prefix}tooltip-bg: #{$tooltip-bg};
|
||||
|
|
@ -15,11 +14,12 @@
|
|||
--#{$prefix}tooltip-arrow-height: #{$tooltip-arrow-height};
|
||||
// scss-docs-end tooltip-css-vars
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: var(--#{$prefix}tooltip-zindex);
|
||||
display: block;
|
||||
padding: var(--#{$prefix}tooltip-arrow-height);
|
||||
margin: var(--#{$prefix}tooltip-margin);
|
||||
@include deprecate("`$tooltip-margin`", "v5", "v5.x", true);
|
||||
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
|
||||
// So reset our font and text properties to avoid inheriting weird values.
|
||||
@include reset-text();
|
||||
|
|
@ -30,83 +30,44 @@
|
|||
|
||||
&.show { opacity: var(--#{$prefix}tooltip-opacity); }
|
||||
|
||||
.tooltip-arrow {
|
||||
display: block;
|
||||
width: var(--#{$prefix}tooltip-arrow-width);
|
||||
height: var(--#{$prefix}tooltip-arrow-height);
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bs-tooltip-top .tooltip-arrow {
|
||||
.tooltip[data-bs-placement="top"]::before {
|
||||
bottom: 0;
|
||||
|
||||
&::before {
|
||||
top: -1px;
|
||||
left: 50%;
|
||||
border-width: var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
|
||||
border-top-color: var(--#{$prefix}tooltip-bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:begin:ignore */
|
||||
.bs-tooltip-end .tooltip-arrow {
|
||||
left: 0;
|
||||
width: var(--#{$prefix}tooltip-arrow-height);
|
||||
height: var(--#{$prefix}tooltip-arrow-width);
|
||||
|
||||
&::before {
|
||||
right: -1px;
|
||||
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
|
||||
border-right-color: var(--#{$prefix}tooltip-bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:end:ignore */
|
||||
|
||||
.bs-tooltip-bottom .tooltip-arrow {
|
||||
.tooltip[data-bs-placement="bottom"]::before {
|
||||
top: 0;
|
||||
|
||||
&::before {
|
||||
bottom: -1px;
|
||||
left: 50%;
|
||||
border-width: 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height); // stylelint-disable-line function-disallowed-list
|
||||
border-bottom-color: var(--#{$prefix}tooltip-bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:begin:ignore */
|
||||
.bs-tooltip-start .tooltip-arrow {
|
||||
right: 0;
|
||||
width: var(--#{$prefix}tooltip-arrow-height);
|
||||
height: var(--#{$prefix}tooltip-arrow-width);
|
||||
.tooltip[data-bs-placement="right"]::before {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height) calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0; // stylelint-disable-line function-disallowed-list
|
||||
border-right-color: var(--#{$prefix}tooltip-bg);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: -1px;
|
||||
.tooltip[data-bs-placement="left"]::before {
|
||||
top: 50%;
|
||||
right: 0;
|
||||
border-width: calc(var(--#{$prefix}tooltip-arrow-width) * .5) 0 calc(var(--#{$prefix}tooltip-arrow-width) * .5) var(--#{$prefix}tooltip-arrow-height); // stylelint-disable-line function-disallowed-list
|
||||
border-left-color: var(--#{$prefix}tooltip-bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* rtl:end:ignore */
|
||||
|
||||
.bs-tooltip-auto {
|
||||
&[data-popper-placement^="top"] {
|
||||
@extend .bs-tooltip-top;
|
||||
}
|
||||
&[data-popper-placement^="right"] {
|
||||
@extend .bs-tooltip-end;
|
||||
}
|
||||
&[data-popper-placement^="bottom"] {
|
||||
@extend .bs-tooltip-bottom;
|
||||
}
|
||||
&[data-popper-placement^="left"] {
|
||||
@extend .bs-tooltip-start;
|
||||
}
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
// Wrapper for the tooltip content
|
||||
|
|
|
|||
|
|
@ -1299,7 +1299,6 @@ $tooltip-border-radius: $border-radius !default;
|
|||
$tooltip-opacity: .9 !default;
|
||||
$tooltip-padding-y: $spacer * .25 !default;
|
||||
$tooltip-padding-x: $spacer * .5 !default;
|
||||
$tooltip-margin: null !default; // TODO: remove this in v6
|
||||
|
||||
$tooltip-arrow-width: .8rem !default;
|
||||
$tooltip-arrow-height: .4rem !default;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
// Instantiate all tooltips in a docs or StackBlitz page
|
||||
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
.forEach(tooltip => {
|
||||
new bootstrap.Tooltip(tooltip)
|
||||
new bootstrap.Tooltip(tooltip, { trigger: 'click' })
|
||||
})
|
||||
|
||||
// --------
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ toc: true
|
|||
|
||||
Dropdowns are toggleable, contextual overlays for displaying lists of links and more. They're made interactive with the included Bootstrap dropdown JavaScript plugin. They're toggled by clicking, not by hovering; this is [an intentional design decision](https://markdotto.com/2012/02/27/bootstrap-explained-dropdowns/).
|
||||
|
||||
Dropdowns are built on a third party library, [Popper](https://popper.js.org/), which provides dynamic positioning and viewport detection. Be sure to include [popper.min.js]({{< param "cdn.popper" >}}) before Bootstrap's JavaScript or use `bootstrap.bundle.min.js` / `bootstrap.bundle.js` which contains Popper. Popper isn't used to position dropdowns in navbars though as dynamic positioning isn't required.
|
||||
Dropdowns are built on a third party library, [Popper](https://popper.js.org/), which provides dynamic positioning and viewport detection. Be sure to include [popper.min.js]({{< param "cdn.floating_ui" >}}) before Bootstrap's JavaScript or use `bootstrap.bundle.min.js` / `bootstrap.bundle.js` which contains Popper. Popper isn't used to position dropdowns in navbars though as dynamic positioning isn't required.
|
||||
|
||||
## Accessibility
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ toc: true
|
|||
|
||||
Things to know when using the popover plugin:
|
||||
|
||||
- Popovers rely on the third party library [Popper](https://popper.js.org/) for positioning. You must include [popper.min.js]({{< param "cdn.popper" >}}) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
|
||||
- Popovers rely on the third party library [Popper](https://popper.js.org/) for positioning. You must include [popper.min.js]({{< param "cdn.floating_ui" >}}) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
|
||||
- Popovers require the [popover plugin]({{< docsref "/components/popovers" >}}) as a dependency.
|
||||
- Popovers are opt-in for performance reasons, so **you must initialize them yourself**.
|
||||
- Zero-length `title` and `content` values will never show a popover.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ toc: true
|
|||
|
||||
Things to know when using the tooltip plugin:
|
||||
|
||||
- Tooltips rely on the third party library [Popper](https://popper.js.org/) for positioning. You must include [popper.min.js]({{< param "cdn.popper" >}}) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
|
||||
- Tooltips rely on the third party library [Popper](https://popper.js.org/) for positioning. You must include [popper.min.js]({{< param "cdn.floating_ui" >}}) before `bootstrap.js`, or use one `bootstrap.bundle.min.js` which contains Popper.
|
||||
- Tooltips are opt-in for performance reasons, so **you must initialize them yourself**.
|
||||
- Tooltips with zero-length titles are never displayed.
|
||||
- Specify `container: 'body'` to avoid rendering problems in more complex components (like our input groups, button groups, etc).
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Skip the download with [jsDelivr](https://www.jsdelivr.com/) to deliver cached v
|
|||
If you're using our compiled JavaScript and prefer to include Popper separately, add Popper before our JS, via a CDN preferably.
|
||||
|
||||
```html
|
||||
<script src="{{< param "cdn.popper" >}}" integrity="{{< param "cdn.popper_hash" >}}" crossorigin="anonymous"></script>
|
||||
<script src="{{< param "cdn.floating_ui" >}}" integrity="{{< param "cdn.floating_ui_hash" >}}" crossorigin="anonymous"></script>
|
||||
<script src="{{< param "cdn.js" >}}" integrity="{{< param "cdn.js_hash" >}}" crossorigin="anonymous"></script>
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ Get started by including Bootstrap's production-ready CSS and JavaScript via CDN
|
|||
You can also include [Popper](https://popper.js.org/) and our JS separately. If you don't plan to use dropdowns, popovers, or tooltips, save some kilobytes by not including Popper.
|
||||
|
||||
```html
|
||||
<script src="{{< param "cdn.popper" >}}" integrity="{{< param "cdn.popper_hash" >}}" crossorigin="anonymous"></script>
|
||||
<script src="{{< param "cdn.floating_ui" >}}" integrity="{{< param "cdn.floating_ui_hash" >}}" crossorigin="anonymous"></script>
|
||||
<script src="{{< param "cdn.js" >}}" integrity="{{< param "cdn.js_hash" >}}" crossorigin="anonymous"></script>
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ To fix this, you can use an `importmap` to resolve the arbitrary module names to
|
|||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@popperjs/core": "{{< param "cdn.popper" >}}",
|
||||
"@popperjs/core": "{{< param "cdn.floating_ui" >}}",
|
||||
"bootstrap": "https://cdn.jsdelivr.net/npm/bootstrap@{{< param "current_version" >}}/dist/js/bootstrap.esm.min.js"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ You can see the above requirements reflected in this modified RTL starter templa
|
|||
|
||||
<!-- Option 2: Separate Popper and Bootstrap JS -->
|
||||
<!--
|
||||
<script src="{{< param "cdn.popper" >}}" integrity="{{< param "cdn.popper_hash" >}}" crossorigin="anonymous"></script>
|
||||
<script src="{{< param "cdn.floating_ui" >}}" integrity="{{< param "cdn.floating_ui_hash" >}}" crossorigin="anonymous"></script>
|
||||
<script src="{{< param "cdn.js" >}}" integrity="{{< param "cdn.js_hash" >}}" crossorigin="anonymous"></script>
|
||||
-->
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue