Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/twbs/bootstrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohann-S <johann.servoire@gmail.com>2020-06-19 11:17:01 +0300
committerXhmikosR <xhmikosr@gmail.com>2020-12-06 19:42:40 +0300
commitadfdf7160b5822aae12eea677e7dd3128d2569bf (patch)
treedc09bbdff9ce3457867d28aadc583f0de6da0ec2
parent5f89ea3a0f9b56547eb03b98afcd189b89d7e5a6 (diff)
Update to popper.js v2.x
-rw-r--r--build/build-plugins.js6
-rw-r--r--build/generate-sri.js2
-rw-r--r--build/rollup.config.js9
-rw-r--r--config.yml4
-rw-r--r--js/src/dropdown.js56
-rw-r--r--js/src/tooltip.js109
-rw-r--r--js/tests/integration/bundle-modularity.js2
-rw-r--r--js/tests/integration/bundle.js1
-rw-r--r--js/tests/integration/rollup.bundle.js4
-rw-r--r--js/tests/karma.conf.js4
-rw-r--r--js/tests/unit/dropdown.spec.js95
-rw-r--r--js/tests/unit/tooltip.spec.js24
-rw-r--r--js/tests/visual/dropdown.html15
-rw-r--r--js/tests/visual/popover.html2
-rw-r--r--js/tests/visual/tooltip.html2
-rw-r--r--nuget/bootstrap.nuspec2
-rw-r--r--nuget/bootstrap.sass.nuspec2
-rw-r--r--package-lock.json22
-rw-r--r--package.json9
-rw-r--r--scss/_dropdown.scss8
-rw-r--r--scss/_popover.scss8
-rw-r--r--scss/_tooltip.scss16
-rw-r--r--site/content/docs/5.0/components/dropdowns.md16
-rw-r--r--site/content/docs/5.0/components/tooltips.md20
-rw-r--r--site/content/docs/5.0/getting-started/webpack.md2
-rw-r--r--site/content/docs/5.0/migration.md2
26 files changed, 145 insertions, 297 deletions
diff --git a/build/build-plugins.js b/build/build-plugins.js
index 7deda49b12..78f76622a4 100644
--- a/build/build-plugins.js
+++ b/build/build-plugins.js
@@ -14,6 +14,7 @@ const rollup = require('rollup')
const { babel } = require('@rollup/plugin-babel')
const banner = require('./banner.js')
+const rootPath = path.resolve(__dirname, '../js/dist/')
const plugins = [
babel({
// Only transpile our source code
@@ -39,7 +40,6 @@ const bsPlugins = {
Toast: path.resolve(__dirname, '../js/src/toast.js'),
Tooltip: path.resolve(__dirname, '../js/src/tooltip.js')
}
-const rootPath = path.resolve(__dirname, '../js/dist/')
const defaultPluginConfig = {
external: [
@@ -87,9 +87,9 @@ const getConfigByPluginKey = pluginKey => {
if (pluginKey === 'Dropdown' || pluginKey === 'Tooltip') {
const config = Object.assign(defaultPluginConfig)
- config.external.push(bsPlugins.Manipulator, 'popper.js')
+ config.external.push(bsPlugins.Manipulator, '@popperjs/core')
config.globals[bsPlugins.Manipulator] = 'Manipulator'
- config.globals['popper.js'] = 'Popper'
+ config.globals['@popperjs/core'] = 'Popper'
return config
}
diff --git a/build/generate-sri.js b/build/generate-sri.js
index 0c272ceadd..8a2e59360a 100644
--- a/build/generate-sri.js
+++ b/build/generate-sri.js
@@ -42,7 +42,7 @@ const files = [
configPropertyName: 'js_bundle_hash'
},
{
- file: 'node_modules/popper.js/dist/umd/popper.min.js',
+ file: 'node_modules/@popperjs/core/dist/umd/popper.min.js',
configPropertyName: 'popper_hash'
}
]
diff --git a/build/rollup.config.js b/build/rollup.config.js
index 05579d165a..7f9c1c7e11 100644
--- a/build/rollup.config.js
+++ b/build/rollup.config.js
@@ -3,13 +3,14 @@
const path = require('path')
const { babel } = require('@rollup/plugin-babel')
const { nodeResolve } = require('@rollup/plugin-node-resolve')
+const replace = require('@rollup/plugin-replace')
const banner = require('./banner.js')
const BUNDLE = process.env.BUNDLE === 'true'
const ESM = process.env.ESM === 'true'
let fileDest = `bootstrap${ESM ? '.esm' : ''}`
-const external = ['popper.js']
+const external = ['@popperjs/core']
const plugins = [
babel({
// Only transpile our source code
@@ -19,15 +20,15 @@ const plugins = [
})
]
const globals = {
- 'popper.js': 'Popper'
+ '@popperjs/core': 'Popper'
}
if (BUNDLE) {
fileDest += '.bundle'
// Remove last entry in external array to bundle Popper
external.pop()
- delete globals['popper.js']
- plugins.push(nodeResolve())
+ delete globals['@popperjs/core']
+ plugins.push(replace({ 'process.env.NODE_ENV': '"production"' }), nodeResolve())
}
const rollupConfig = {
diff --git a/config.yml b/config.yml
index d109da5213..2bdc700bce 100644
--- a/config.yml
+++ b/config.yml
@@ -75,5 +75,5 @@ params:
js_hash: "sha384-supZtwqjyYg6XvvTCi4/w6J6Hm6IKqXaaeoyGhIhonCdkSvA70sSucW7OqXIo4lZ"
js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-alpha3/dist/js/bootstrap.bundle.min.js"
js_bundle_hash: "sha384-G/J8d6sz9bTod37AsZzNtTwT77J24FKjJEO1YsU2vW7iPcmYP3/tznu+LcK824t9"
- popper: "https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
- popper_hash: "sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
+ popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.4.2/dist/umd/popper.min.js"
+ popper_hash: "sha384-a46n7BtEJaPKKs2SeVxZzwKkapYzBUr8c7DyCLEpkRrs4LE03nlh53ZSOPgkJB7U"
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index 0ac108ab81..04c299600e 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -5,6 +5,8 @@
* --------------------------------------------------------------------------
*/
+import * as Popper from '@popperjs/core'
+
import {
getjQuery,
onDOMContentLoaded,
@@ -18,7 +20,6 @@ import {
import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
-import Popper from 'popper.js'
import SelectorEngine from './dom/selector-engine'
import BaseComponent from './base-component'
@@ -58,7 +59,6 @@ const CLASS_NAME_DROPEND = 'dropend'
const CLASS_NAME_DROPSTART = 'dropstart'
const CLASS_NAME_MENUEND = 'dropdown-menu-end'
const CLASS_NAME_NAVBAR = 'navbar'
-const CLASS_NAME_POSITION_STATIC = 'position-static'
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="dropdown"]'
const SELECTOR_FORM_CHILD = '.dropdown form'
@@ -76,7 +76,7 @@ const PLACEMENT_LEFT = isRTL ? 'right-start' : 'left-start'
const Default = {
offset: 0,
flip: true,
- boundary: 'scrollParent',
+ boundary: 'clippingParents',
reference: 'toggle',
display: 'dynamic',
popperConfig: null
@@ -176,14 +176,7 @@ class Dropdown extends BaseComponent {
}
}
- // If boundary is not `scrollParent`, then set position to `static`
- // to allow the menu to "escape" the scroll parent's boundaries
- // https://github.com/twbs/bootstrap/issues/24251
- if (this._config.boundary !== 'scrollParent') {
- parent.classList.add(CLASS_NAME_POSITION_STATIC)
- }
-
- this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())
+ this._popper = Popper.createPopper(referenceElement, this._menu, this._getPopperConfig())
}
// If this is a touch-enabled device we add extra
@@ -233,6 +226,7 @@ class Dropdown extends BaseComponent {
super.dispose()
EventHandler.off(this._element, EVENT_KEY)
this._menu = null
+
if (this._popper) {
this._popper.destroy()
this._popper = null
@@ -242,7 +236,7 @@ class Dropdown extends BaseComponent {
update() {
this._inNavbar = this._detectNavbar()
if (this._popper) {
- this._popper.scheduleUpdate()
+ this._popper.update()
}
}
@@ -296,44 +290,24 @@ class Dropdown extends BaseComponent {
return Boolean(this._element.closest(`.${CLASS_NAME_NAVBAR}`))
}
- _getOffset() {
- const offset = {}
-
- if (typeof this._config.offset === 'function') {
- offset.fn = data => {
- data.offsets = {
- ...data.offsets,
- ...(this._config.offset(data.offsets, this._element) || {})
- }
-
- return data
- }
- } else {
- offset.offset = this._config.offset
- }
-
- return offset
- }
-
_getPopperConfig() {
const popperConfig = {
placement: this._getPlacement(),
- modifiers: {
- offset: this._getOffset(),
- flip: {
- enabled: this._config.flip
- },
- preventOverflow: {
- boundariesElement: this._config.boundary
+ modifiers: [{
+ name: 'preventOverflow',
+ options: {
+ altBoundary: this._config.flip,
+ rootBoundary: this._config.boundary
}
- }
+ }]
}
// Disable Popper if we have a static display
if (this._config.display === 'static') {
- popperConfig.modifiers.applyStyle = {
+ popperConfig.modifiers = [{
+ name: 'applyStyles',
enabled: false
- }
+ }]
}
return {
diff --git a/js/src/tooltip.js b/js/src/tooltip.js
index 17148ed9a6..dc2f83a8a5 100644
--- a/js/src/tooltip.js
+++ b/js/src/tooltip.js
@@ -5,6 +5,8 @@
* --------------------------------------------------------------------------
*/
+import * as Popper from '@popperjs/core'
+
import {
getjQuery,
onDOMContentLoaded,
@@ -25,7 +27,6 @@ import {
import Data from './dom/data'
import EventHandler from './dom/event-handler'
import Manipulator from './dom/manipulator'
-import Popper from 'popper.js'
import SelectorEngine from './dom/selector-engine'
import BaseComponent from './base-component'
@@ -51,9 +52,8 @@ const DefaultType = {
html: 'boolean',
selector: '(string|boolean)',
placement: '(string|function)',
- offset: '(number|string|function)',
container: '(string|element|boolean)',
- fallbackPlacement: '(string|array)',
+ fallbackPlacements: '(null|array)',
boundary: '(string|element)',
customClass: '(string|function)',
sanitize: 'boolean',
@@ -82,10 +82,9 @@ const Default = {
html: false,
selector: false,
placement: 'top',
- offset: 0,
container: false,
- fallbackPlacement: 'flip',
- boundary: 'scrollParent',
+ fallbackPlacements: null,
+ boundary: 'clippingParents',
customClass: '',
sanitize: true,
sanitizeFn: null,
@@ -287,7 +286,7 @@ class Tooltip extends BaseComponent {
EventHandler.trigger(this._element, this.constructor.Event.INSERTED)
- this._popper = new Popper(this._element, tip, this._getPopperConfig(attachment))
+ this._popper = Popper.createPopper(this._element, tip, this._getPopperConfig(attachment))
tip.classList.add(CLASS_NAME_SHOW)
@@ -307,13 +306,9 @@ class Tooltip extends BaseComponent {
}
const complete = () => {
- if (this.config.animation) {
- this._fixTransition()
- }
-
const prevHoverState = this._hoverState
- this._hoverState = null
+ this._hoverState = null
EventHandler.trigger(this._element, this.constructor.Event.SHOWN)
if (prevHoverState === HOVER_STATE_OUT) {
@@ -345,7 +340,11 @@ class Tooltip extends BaseComponent {
this._cleanTipClass()
this._element.removeAttribute('aria-describedby')
EventHandler.trigger(this._element, this.constructor.Event.HIDDEN)
- this._popper.destroy()
+
+ if (this._popper) {
+ this._popper.destroy()
+ this._popper = null
+ }
}
const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE)
@@ -380,7 +379,7 @@ class Tooltip extends BaseComponent {
update() {
if (this._popper !== null) {
- this._popper.scheduleUpdate()
+ this._popper.update()
}
}
@@ -469,26 +468,45 @@ class Tooltip extends BaseComponent {
// Private
_getPopperConfig(attachment) {
+ const flipModifier = {
+ name: 'flip',
+ options: {
+ altBoundary: true
+ }
+ }
+
+ if (this.config.fallbackPlacements) {
+ flipModifier.options.fallbackPlacements = this.config.fallbackPlacements
+ }
+
const defaultBsConfig = {
placement: attachment,
- modifiers: {
- offset: this._getOffset(),
- flip: {
- behavior: this.config.fallbackPlacement
+ modifiers: [
+ flipModifier,
+ {
+ name: 'preventOverflow',
+ options: {
+ rootBoundary: this.config.boundary
+ }
},
- arrow: {
- element: `.${this.constructor.NAME}-arrow`
+ {
+ name: 'arrow',
+ options: {
+ element: `.${this.constructor.NAME}-arrow`
+ }
},
- preventOverflow: {
- boundariesElement: this.config.boundary
+ {
+ name: 'onChange',
+ enabled: true,
+ phase: 'afterWrite',
+ fn: data => this._handlePopperPlacementChange(data)
}
- },
- onCreate: data => {
- if (data.originalPlacement !== data.placement) {
+ ],
+ onFirstUpdate: data => {
+ if (data.options.placement !== data.placement) {
this._handlePopperPlacementChange(data)
}
- },
- onUpdate: data => this._handlePopperPlacementChange(data)
+ }
}
return {
@@ -501,25 +519,6 @@ class Tooltip extends BaseComponent {
this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`)
}
- _getOffset() {
- const offset = {}
-
- if (typeof this.config.offset === 'function') {
- offset.fn = data => {
- data.offsets = {
- ...data.offsets,
- ...(this.config.offset(data.offsets, this._element) || {})
- }
-
- return data
- }
- } else {
- offset.offset = this.config.offset
- }
-
- return offset
- }
-
_getContainer() {
if (this.config.container === false) {
return document.body
@@ -743,23 +742,15 @@ class Tooltip extends BaseComponent {
}
_handlePopperPlacementChange(popperData) {
- this.tip = popperData.instance.popper
- this._cleanTipClass()
- this._addAttachmentClass(this._getAttachment(popperData.placement))
- }
+ const { state } = popperData
- _fixTransition() {
- const tip = this.getTipElement()
- const initConfigAnimation = this.config.animation
- if (tip.getAttribute('x-placement') !== null) {
+ if (!state) {
return
}
- tip.classList.remove(CLASS_NAME_FADE)
- this.config.animation = false
- this.hide()
- this.show()
- this.config.animation = initConfigAnimation
+ this.tip = state.elements.popper
+ this._cleanTipClass()
+ this._addAttachmentClass(this._getAttachment(state.placement))
}
// Static
diff --git a/js/tests/integration/bundle-modularity.js b/js/tests/integration/bundle-modularity.js
index 003f840210..8546141b19 100644
--- a/js/tests/integration/bundle-modularity.js
+++ b/js/tests/integration/bundle-modularity.js
@@ -1,5 +1,5 @@
-import 'popper.js'
import Tooltip from '../../dist/tooltip'
+import '../../dist/carousel'
window.addEventListener('load', () => {
[].concat(...document.querySelectorAll('[data-bs-toggle="tooltip"]'))
diff --git a/js/tests/integration/bundle.js b/js/tests/integration/bundle.js
index 75982f76f9..452088a7d8 100644
--- a/js/tests/integration/bundle.js
+++ b/js/tests/integration/bundle.js
@@ -1,4 +1,3 @@
-import 'popper.js'
import { Tooltip } from '../../../dist/js/bootstrap.esm.js'
window.addEventListener('load', () => {
diff --git a/js/tests/integration/rollup.bundle.js b/js/tests/integration/rollup.bundle.js
index 9e2ed26c1c..288f40961d 100644
--- a/js/tests/integration/rollup.bundle.js
+++ b/js/tests/integration/rollup.bundle.js
@@ -2,6 +2,7 @@
const { babel } = require('@rollup/plugin-babel')
const { nodeResolve } = require('@rollup/plugin-node-resolve')
+const replace = require('@rollup/plugin-replace')
module.exports = {
input: 'js/tests/integration/bundle.js',
@@ -10,6 +11,9 @@ module.exports = {
format: 'iife'
},
plugins: [
+ replace({
+ 'process.env.NODE_ENV': '"production"'
+ }),
nodeResolve(),
babel({
exclude: 'node_modules/**',
diff --git a/js/tests/karma.conf.js b/js/tests/karma.conf.js
index 0728a8cfa4..d0dd8bdd90 100644
--- a/js/tests/karma.conf.js
+++ b/js/tests/karma.conf.js
@@ -5,6 +5,7 @@ const ip = require('ip')
const { babel } = require('@rollup/plugin-babel')
const istanbul = require('rollup-plugin-istanbul')
const { nodeResolve } = require('@rollup/plugin-node-resolve')
+const replace = require('@rollup/plugin-replace')
const {
browsers,
@@ -74,6 +75,9 @@ const conf = {
},
rollupPreprocessor: {
plugins: [
+ replace({
+ 'process.env.NODE_ENV': '"dev"'
+ }),
istanbul({
exclude: [
'node_modules/**',
diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js
index f6a5feb1b9..d2171f3697 100644
--- a/js/tests/unit/dropdown.spec.js
+++ b/js/tests/unit/dropdown.spec.js
@@ -1,5 +1,3 @@
-import Popper from 'popper.js'
-
import Dropdown from '../../src/dropdown'
import EventHandler from '../../src/dom/event-handler'
@@ -36,50 +34,6 @@ describe('Dropdown', () => {
})
describe('constructor', () => {
- it('should create offset modifier correctly when offset option is a function', () => {
- fixtureEl.innerHTML = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].join('')
-
- const getOffset = offsets => offsets
- const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
- const dropdown = new Dropdown(btnDropdown, {
- offset: getOffset
- })
-
- const offset = dropdown._getOffset()
-
- expect(offset.offset).toBeUndefined()
- expect(typeof offset.fn).toEqual('function')
- })
-
- it('should create offset modifier correctly when offset option is not a function', () => {
- fixtureEl.innerHTML = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].join('')
-
- const myOffset = 7
- const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
- const dropdown = new Dropdown(btnDropdown, {
- offset: myOffset
- })
-
- const offset = dropdown._getOffset()
-
- expect(offset.offset).toEqual(myOffset)
- expect(offset.fn).toBeUndefined()
- })
-
it('should add a listener on trigger which do not have data-bs-toggle="dropdown"', () => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
@@ -860,14 +814,11 @@ describe('Dropdown', () => {
expect(dropdown._menu).toBeDefined()
expect(dropdown._element).toBeDefined()
- spyOn(Popper.prototype, 'destroy')
-
dropdown.dispose()
expect(dropdown._popper).toBeNull()
expect(dropdown._menu).toBeNull()
expect(dropdown._element).toBeNull()
- expect(Popper.prototype.destroy).toHaveBeenCalled()
})
})
@@ -889,12 +840,12 @@ describe('Dropdown', () => {
expect(dropdown._popper).toBeDefined()
- spyOn(dropdown._popper, 'scheduleUpdate')
+ spyOn(dropdown._popper, 'update')
spyOn(dropdown, '_detectNavbar')
dropdown.update()
- expect(dropdown._popper.scheduleUpdate).toHaveBeenCalled()
+ expect(dropdown._popper.update).toHaveBeenCalled()
expect(dropdown._detectNavbar).toHaveBeenCalled()
})
@@ -921,48 +872,6 @@ describe('Dropdown', () => {
})
describe('data-api', () => {
- it('should not add class position-static to dropdown if boundary not set', done => {
- fixtureEl.innerHTML = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].join('')
-
- const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
- const dropdownEl = fixtureEl.querySelector('.dropdown')
-
- dropdownEl.addEventListener('shown.bs.dropdown', () => {
- expect(dropdownEl.classList.contains('position-static')).toEqual(false)
- done()
- })
-
- btnDropdown.click()
- })
-
- it('should add class position-static to dropdown if boundary not scrollParent', done => {
- fixtureEl.innerHTML = [
- '<div class="dropdown">',
- ' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" data-bs-boundary="viewport">Dropdown</button>',
- ' <div class="dropdown-menu">',
- ' <a class="dropdown-item" href="#">Secondary link</a>',
- ' </div>',
- '</div>'
- ].join('')
-
- const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
- const dropdownEl = fixtureEl.querySelector('.dropdown')
-
- dropdownEl.addEventListener('shown.bs.dropdown', () => {
- expect(dropdownEl.classList.contains('position-static')).toEqual(true)
- done()
- })
-
- btnDropdown.click()
- })
-
it('should show and hide a dropdown', done => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js
index 9ea9096de9..9fc306dfe1 100644
--- a/js/tests/unit/tooltip.spec.js
+++ b/js/tests/unit/tooltip.spec.js
@@ -483,24 +483,6 @@ describe('Tooltip', () => {
tooltip.show()
})
- it('should show a tooltip with offset as a function', done => {
- fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
-
- const spy = jasmine.createSpy('offset').and.returnValue({})
- const tooltipEl = fixtureEl.querySelector('a')
- const tooltip = new Tooltip(tooltipEl, {
- offset: spy
- })
-
- tooltipEl.addEventListener('shown.bs.tooltip', () => {
- expect(document.querySelector('.tooltip')).toBeDefined()
- expect(spy).toHaveBeenCalled()
- done()
- })
-
- tooltip.show()
- })
-
it('should show a tooltip without the animation', done => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
@@ -789,18 +771,18 @@ describe('Tooltip', () => {
})
describe('update', () => {
- it('should call popper schedule update', done => {
+ it('should call popper update', done => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip">'
const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl)
tooltipEl.addEventListener('shown.bs.tooltip', () => {
- spyOn(tooltip._popper, 'scheduleUpdate')
+ spyOn(tooltip._popper, 'update')
tooltip.update()
- expect(tooltip._popper.scheduleUpdate).toHaveBeenCalled()
+ expect(tooltip._popper.update).toHaveBeenCalled()
done()
})
diff --git a/js/tests/visual/dropdown.html b/js/tests/visual/dropdown.html
index 930940a157..374e46e1ae 100644
--- a/js/tests/visual/dropdown.html
+++ b/js/tests/visual/dropdown.html
@@ -78,7 +78,9 @@
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</div>
+ </div>
+ <div class="col-sm-12 mt-4">
<div class="btn-group dropup">
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropup</button>
<ul class="dropdown-menu">
@@ -172,16 +174,6 @@
<div class="row">
<div class="col-sm-3 mt-4">
<div class="btn-group dropdown">
- <button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" data-bs-offset="10,20">Dropdown offset</button>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="#">Action</a></li>
- <li><a class="dropdown-item" href="#">Another action</a></li>
- <li><a class="dropdown-item" href="#">Something else here</a></li>
- </ul>
- </div>
- </div>
- <div class="col-sm-3 mt-4">
- <div class="btn-group dropdown">
<button type="button" class="btn btn-secondary">Dropdown reference</button>
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" data-bs-reference="parent">
<span class="visually-hidden">Dropdown split</span>
@@ -206,10 +198,9 @@
</div>
</div>
</div>
-
</div>
- <script src="../../../node_modules/popper.js/dist/umd/popper.min.js"></script>
+ <script src="../../../node_modules/@popperjs/core/dist/umd/popper.min.js"></script>
<script src="../../dist/dom/event-handler.js"></script>
<script src="../../dist/dom/selector-engine.js"></script>
<script src="../../dist/dom/data.js"></script>
diff --git a/js/tests/visual/popover.html b/js/tests/visual/popover.html
index c758253969..ddc068708d 100644
--- a/js/tests/visual/popover.html
+++ b/js/tests/visual/popover.html
@@ -31,7 +31,7 @@
</button>
</div>
- <script src="../../../node_modules/popper.js/dist/umd/popper.min.js"></script>
+ <script src="../../../node_modules/@popperjs/core/dist/umd/popper.min.js"></script>
<script src="../../dist/dom/event-handler.js"></script>
<script src="../../dist/dom/selector-engine.js"></script>
<script src="../../dist/dom/manipulator.js"></script>
diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html
index bade26a6c0..36f0a70575 100644
--- a/js/tests/visual/tooltip.html
+++ b/js/tests/visual/tooltip.html
@@ -68,7 +68,7 @@
<div id="customContainer"></div>
</div>
- <script src="../../../node_modules/popper.js/dist/umd/popper.min.js"></script>
+ <script src="../../../node_modules/@popperjs/core/dist/umd/popper.min.js"></script>
<script src="../../dist/dom/selector-engine.js"></script>
<script src="../../dist/dom/event-handler.js"></script>
<script src="../../dist/dom/manipulator.js"></script>
diff --git a/nuget/bootstrap.nuspec b/nuget/bootstrap.nuspec
index 2f8696d41b..50888a0b77 100644
--- a/nuget/bootstrap.nuspec
+++ b/nuget/bootstrap.nuspec
@@ -17,7 +17,7 @@
<copyright>Copyright 2017-2020</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<dependencies>
- <dependency id="popper.js" version="[1.16.1,2)" />
+ <dependency id="@popperjs/core" version="[2.4.2,3)" />
</dependencies>
<tags>css mobile-first responsive front-end framework web</tags>
<contentFiles>
diff --git a/nuget/bootstrap.sass.nuspec b/nuget/bootstrap.sass.nuspec
index 99d406ffa4..78ee63e737 100644
--- a/nuget/bootstrap.sass.nuspec
+++ b/nuget/bootstrap.sass.nuspec
@@ -17,7 +17,7 @@
<copyright>Copyright 2017-2020</copyright>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<dependencies>
- <dependency id="popper.js" version="[1.16.1,2)" />
+ <dependency id="@popperjs/core" version="[2.4.2,3)" />
</dependencies>
<tags>css sass mobile-first responsive front-end framework web</tags>
<contentFiles>
diff --git a/package-lock.json b/package-lock.json
index 3d7aab1025..f029e4f39b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1157,6 +1157,12 @@
"fastq": "^1.6.0"
}
},
+ "@popperjs/core": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.4.2.tgz",
+ "integrity": "sha512-JlGTGRYHC2QK+DDbePyXdBdooxFq2+noLfWpRqJtkxcb/oYWzOF0kcbfvvbWrwevCC1l6hLUg1wHYT+ona5BWQ==",
+ "dev": true
+ },
"@rollup/plugin-babel": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz",
@@ -1204,6 +1210,16 @@
"resolve": "^1.19.0"
}
},
+ "@rollup/plugin-replace": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz",
+ "integrity": "sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==",
+ "dev": true,
+ "requires": {
+ "@rollup/pluginutils": "^3.1.0",
+ "magic-string": "^0.25.7"
+ }
+ },
"@rollup/pluginutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
@@ -8228,12 +8244,6 @@
"integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
"dev": true
},
- "popper.js": {
- "version": "1.16.1",
- "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
- "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
- "dev": true
- },
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
diff --git a/package.json b/package.json
index a1d125b314..df9b5c63d4 100644
--- a/package.json
+++ b/package.json
@@ -95,15 +95,17 @@
},
"dependencies": {},
"peerDependencies": {
- "popper.js": "^1.16.1"
+ "@popperjs/core": "^2.4.2"
},
"devDependencies": {
"@babel/cli": "^7.12.8",
"@babel/core": "^7.12.9",
"@babel/preset-env": "^7.12.7",
+ "@popperjs/core": "^2.4.2",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
+ "@rollup/plugin-replace": "^2.3.4",
"autoprefixer": "^10.0.4",
"bundlewatch": "^0.3.1",
"clean-css-cli": "^4.3.0",
@@ -131,7 +133,6 @@
"lockfile-lint": "^4.3.7",
"nodemon": "^2.0.6",
"npm-run-all": "^4.1.5",
- "popper.js": "^1.16.1",
"postcss": "^8.1.10",
"postcss-cli": "^8.3.0",
"rollup": "^2.34.0",
@@ -161,13 +162,13 @@
"shim": {
"js/bootstrap": {
"deps": [
- "popper.js"
+ "@popperjs/core"
]
}
},
"dependencies": {},
"peerDependencies": {
- "popper.js": "^1.16.1"
+ "@popperjs/core": "^2.4.2"
}
}
}
diff --git a/scss/_dropdown.scss b/scss/_dropdown.scss
index 7cad640096..9db6937aee 100644
--- a/scss/_dropdown.scss
+++ b/scss/_dropdown.scss
@@ -104,10 +104,10 @@
// When Popper is enabled, reset the basic dropdown position
// stylelint-disable-next-line no-duplicate-selectors
.dropdown-menu {
- &[x-placement^="top"],
- &[x-placement^="right"],
- &[x-placement^="bottom"],
- &[x-placement^="left"] {
+ &[data-popper-placement^="top"],
+ &[data-popper-placement^="right"],
+ &[data-popper-placement^="bottom"],
+ &[data-popper-placement^="left"] {
right: auto;
bottom: auto;
left: auto;
diff --git a/scss/_popover.scss b/scss/_popover.scss
index 6688f729c2..36478b3370 100644
--- a/scss/_popover.scss
+++ b/scss/_popover.scss
@@ -134,16 +134,16 @@
}
.bs-popover-auto {
- &[x-placement^="top"] {
+ &[data-popper-placement^="top"] {
@extend .bs-popover-top;
}
- &[x-placement^="right"] {
+ &[data-popper-placement^="right"] {
@extend .bs-popover-end;
}
- &[x-placement^="bottom"] {
+ &[data-popper-placement^="bottom"] {
@extend .bs-popover-bottom;
}
- &[x-placement^="left"] {
+ &[data-popper-placement^="left"] {
@extend .bs-popover-start;
}
}
diff --git a/scss/_tooltip.scss b/scss/_tooltip.scss
index a98ff4db5f..60c860c674 100644
--- a/scss/_tooltip.scss
+++ b/scss/_tooltip.scss
@@ -36,7 +36,7 @@
bottom: 0;
&::before {
- top: 0;
+ top: -1px;
border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
border-top-color: $tooltip-arrow-color;
}
@@ -52,7 +52,7 @@
height: $tooltip-arrow-width;
&::before {
- right: 0 #{"/* rtl:ignore */"};
+ right: -1px #{"/* rtl:ignore */"};
border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0 #{"/* rtl:ignore */"};
border-right-color: $tooltip-arrow-color #{"/* rtl:ignore */"};
}
@@ -66,7 +66,7 @@
top: 0;
&::before {
- bottom: 0;
+ bottom: -1px;
border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
border-bottom-color: $tooltip-arrow-color;
}
@@ -82,7 +82,7 @@
height: $tooltip-arrow-width;
&::before {
- left: 0 #{"/* rtl:ignore */"};
+ left: -1px #{"/* rtl:ignore */"};
border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height #{"/* rtl:ignore */"};
border-left-color: $tooltip-arrow-color #{"/* rtl:ignore */"};
}
@@ -90,16 +90,16 @@
}
.bs-tooltip-auto {
- &[x-placement^="top"] {
+ &[data-popper-placement^="top"] {
@extend .bs-tooltip-top;
}
- &[x-placement^="right"] {
+ &[data-popper-placement^="right"] {
@extend .bs-tooltip-end;
}
- &[x-placement^="bottom"] {
+ &[data-popper-placement^="bottom"] {
@extend .bs-tooltip-bottom;
}
- &[x-placement^="left"] {
+ &[data-popper-placement^="left"] {
@extend .bs-tooltip-start;
}
}
diff --git a/site/content/docs/5.0/components/dropdowns.md b/site/content/docs/5.0/components/dropdowns.md
index 69a7783dc0..891c9a01b8 100644
--- a/site/content/docs/5.0/components/dropdowns.md
+++ b/site/content/docs/5.0/components/dropdowns.md
@@ -873,32 +873,22 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap
</thead>
<tbody>
<tr>
- <td><code>offset</code></td>
- <td>number | string | function</td>
- <td><code>0</code></td>
- <td>
- <p>Offset of the dropdown relative to its target.</p>
- <p>When a function is used to determine the offset, it is called with an object containing the offset data as its first argument. The function must return an object with the same structure. The triggering element DOM node is passed as the second argument.</p>
- <p>For more information refer to Popper's <a href="https://popper.js.org/docs/v1/#modifiers..offset.offset">offset docs</a>.</p>
- </td>
- </tr>
- <tr>
<td><code>flip</code></td>
<td>boolean</td>
<td><code>true</code></td>
- <td>Allow Dropdown to flip in case of an overlapping on the reference element. For more information refer to Popper's <a href="https://popper.js.org/docs/v1/#modifiers..flip.enabled">flip docs</a>.</td>
+ <td>Allow Dropdown to flip in case of an overlapping on the reference element. For more information refer to Popper's <a href="https://popper.js.org/docs/v2/modifiers/flip/">flip docs</a>.</td>
</tr>
<tr>
<td><code>boundary</code></td>
<td>string | element</td>
<td><code>'scrollParent'</code></td>
- <td>Overflow constraint boundary of the dropdown menu. Accepts the values of <code>'viewport'</code>, <code>'window'</code>, <code>'scrollParent'</code>, or an HTMLElement reference (JavaScript only). For more information refer to Popper's <a href="https://popper.js.org/docs/v1/#modifiers..preventOverflow.boundariesElement">preventOverflow docs</a>.</td>
+ <td>Overflow constraint boundary of the dropdown menu. By default it's <code>'clippingParents'</code> and can accept an HTMLElement reference (JavaScript only). For more information refer to Popper's <a href="https://popper.js.org/docs/v2/utils/detect-overflow/#boundary">preventOverflow docs</a>.</td>
</tr>
<tr>
<td><code>reference</code></td>
<td>string | element</td>
<td><code>'toggle'</code></td>
- <td>Reference element of the dropdown menu. Accepts the values of <code>'toggle'</code>, <code>'parent'</code>, or an HTMLElement reference. For more information refer to Popper's <a href="https://popper.js.org/docs/v1/#referenceObject">referenceObject docs</a>.</td>
+ <td>Reference element of the dropdown menu. Accepts the values of <code>'toggle'</code>, <code>'parent'</code>, or an HTMLElement reference. For more information refer to Popper's <a href="https://popper.js.org/docs/v2/constructors/#createpopper">constructor docs</a>.</td>
</tr>
<tr>
<td><code>display</code></td>
diff --git a/site/content/docs/5.0/components/tooltips.md b/site/content/docs/5.0/components/tooltips.md
index 2ab684a220..e2a45c3edd 100644
--- a/site/content/docs/5.0/components/tooltips.md
+++ b/site/content/docs/5.0/components/tooltips.md
@@ -249,27 +249,17 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt
</td>
</tr>
<tr>
- <td><code>offset</code></td>
- <td>number | string | function</td>
- <td><code>0</code></td>
- <td>
- <p>Offset of the tooltip relative to its target.</p>
- <p>When a function is used to determine the offset, it is called with an object containing the offset data as its first argument. The function must return an object with the same structure. The triggering element DOM node is passed as the second argument.</p>
- <p>For more information refer to Popper's <a href="https://popper.js.org/docs/v1/#modifiers..offset.offset">offset docs</a>.</p>
- </td>
- </tr>
- <tr>
<td><code>fallbackPlacement</code></td>
- <td>string | array</td>
- <td><code>'flip'</code></td>
+ <td>null | array</td>
+ <td><code>null</code></td>
<td>Allow to specify which position Popper will use on fallback. For more information refer to
- Popper's <a href="https://popper.js.org/docs/v1/#modifiers..flip.behavior">behavior docs</a></td>
+ Popper's <a href="https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements">behavior docs</a></td>
</tr>
<tr>
<td><code>boundary</code></td>
<td>string | element</td>
- <td><code>'scrollParent'</code></td>
- <td>Overflow constraint boundary of the tooltip. Accepts the values of <code>'viewport'</code>, <code>'window'</code>, <code>'scrollParent'</code>, or an HTMLElement reference (JavaScript only). For more information refer to Popper's <a href="https://popper.js.org/docs/v1/#modifiers..preventOverflow.boundariesElement">preventOverflow docs</a>.</td>
+ <td><code>'clippingParents'</code></td>
+ <td>Overflow constraint boundary of the tooltip. By default it's <code>'clippingParents'</code> and can accept an HTMLElement reference (JavaScript only). For more information refer to Popper's <a href="https://popper.js.org/docs/v2/utils/detect-overflow/#boundary">preventOverflow docs</a>.</td>
</tr>
<tr>
<td><code>customClass</code></td>
diff --git a/site/content/docs/5.0/getting-started/webpack.md b/site/content/docs/5.0/getting-started/webpack.md
index 4b9c525dd9..6998e1e99c 100644
--- a/site/content/docs/5.0/getting-started/webpack.md
+++ b/site/content/docs/5.0/getting-started/webpack.md
@@ -27,7 +27,7 @@ import Alert from 'bootstrap/js/dist/alert';
```
Bootstrap depends on [Popper](https://popper.js.org/), which is specified in the `peerDependencies` property.
-This means that you will have to make sure to add it to your `package.json` using `npm install popper.js`.
+This means that you will have to make sure to add it to your `package.json` using `npm install @popperjs/core`.
## Importing Styles
diff --git a/site/content/docs/5.0/migration.md b/site/content/docs/5.0/migration.md
index da554c3322..7eef5504f8 100644
--- a/site/content/docs/5.0/migration.md
+++ b/site/content/docs/5.0/migration.md
@@ -283,6 +283,8 @@ Changes to our source and compiled JavaScript files.
- Dropped jQuery dependency and rewrote plugins to be in regular JavaScript.
- Removed underscore from public static methods like `_getInstance()` → `getInstance()`.
+- Moved from Popper v1.x to Popper v2.x
+- Removed `offset` option from our Tooltip/Popover and Dropdown plugin, this can still be achieve using `popperConfig` parameter.
### Color system